Showing posts with label asp.net mvc. Show all posts
Showing posts with label asp.net mvc. Show all posts

Monday, 8 February 2010

Asp.Net MVC Manager for javascript include and Css files

I was trying to figure a way to automatically include javascript from html helpers and from view without having to check if it wasn't already in the master so i came up with a simple manager. It is greatly inspired by Frugal Coder Blog and Chris Pietschmann. I build an abstarct manager to perform the operation required by the javascript and css manager.
so here it is :


using System.Collections.Generic;
using System.Text;
using System.Web.Mvc;

namespace MvcExtensions
{
public abstract class MvcManager
{
protected HtmlHelper _htmlHelper;
protected Dictionary<string, TagBuilder> _include = new Dictionary<string, TagBuilder>();

public MvcManager(HtmlHelper htmlHelper)
{
this._htmlHelper = htmlHelper;
}

public virtual MvcManager Include(string path)
{
if (!this._include.ContainsKey(path))
{
this._include.Add(path, this.BuildTag(UrlHelper.GenerateContentUrl(path, this._htmlHelper.ViewContext.HttpContext)));
}
return this;
}

public virtual MvcHtmlString Render()
{
StringBuilder sb = new StringBuilder();
foreach (var item in this._include.Values)
{
sb.AppendLine(item.ToString());
}
return MvcHtmlString.Create(sb.ToString());
}

protected abstract TagBuilder BuildTag(string src);
}
}


And now for the javascript manager:





using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace MvcExtensions
{
public class MvcClientScriptManager : MvcManager
{
private List<string> _readyLine = new List<string>();

public MvcClientScriptManager(HtmlHelper htmlHelper) : base(htmlHelper) { }

public new MvcClientScriptManager Include(string path)
{
return (MvcClientScriptManager)((MvcManager)this).Include(path);
}
public MvcClientScriptManager Include(string path, string debugPath)
{
string file = this._htmlHelper.ViewContext.HttpContext.IsDebuggingEnabled ? debugPath : path;
return this.Include(file);
}

public MvcClientScriptManager AddToReady(string code)
{
this._readyLine.Add(code);
return this;
}

protected override TagBuilder BuildTag(string src)
{
TagBuilder scriptTag = new TagBuilder("script");
scriptTag.MergeAttribute("type", "text/javascript");
scriptTag.MergeAttribute("src", src);
return scriptTag;
}

public override MvcHtmlString Render()
{
if (this._readyLine.Any())
{
StringBuilder sb = new StringBuilder(base.Render().ToString());
sb.AppendLine("<script type=\"text/javascript\">");
sb.AppendLine("$(function() {");
foreach (var item in this._readyLine)
{
sb.AppendLine("\t" + item);
}
sb.AppendLine("});");
sb.AppendLine("</script>");
return MvcHtmlString.Create(sb.ToString());
}
return base.Render();
}
}
}


The CssManager :


using System.Web.Mvc;

namespace MvcExtensions
{
public class MvcCssManager : MvcManager
{
public MvcCssManager(HtmlHelper htmlHelper) : base(htmlHelper) { }

public new MvcCssManager Include(string path)
{
return (MvcCssManager)base.Include(path);
}

protected override TagBuilder BuildTag(string src)
{
TagBuilder linkTag = new TagBuilder("link");
linkTag.MergeAttribute("type", "text/css");
linkTag.MergeAttribute("rel", "stylesheet");
linkTag.MergeAttribute("href", UrlHelper.GenerateContentUrl(src, this._htmlHelper.ViewContext.HttpContext));
return linkTag;
}
}
}


my master page now looks like this:


<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
<% Html.MvcCssManager().Include("~/Content/Css/Site.css"); %>
<asp:ContentPlaceHolder ID="HeadContent" runat="server" />

<%= Html.MvcCssManager().Render()%>
</head>

<body>
<div class="page">

<div id="header">
<div id="title">
<h1>My MVC Application</h1>
</div>

<div id="logindisplay">
<% Html.RenderPartial("LogOnUserControl"); %>
</div>

<div id="menucontainer">

<ul id="menu">
<li><%= Html.ActionLink("Home", "Index", "Home")%></li>
<li><%= Html.ActionLink("About", "About", "Home")%></li>
<li><%= Html.ActionLink("Users", "List", "UserManagement")%></li>
</ul>

</div>
</div>

<div id="main">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />

<div id="footer">
</div>
</div>
</div>

<%= Html.MvcClientScriptManager().Render() %>

</body>
</html>



And finally a sample view in which I use it:





<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyTestMVC2App.Areas.UserManagement.Models.User>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="HeadContent" runat="server">
<%
Html.MvcClientScriptManager()
.Include("~/Scripts/MicrosoftAjax.js", "~/Scripts/MicrosoftAjax.debug.js")
.Include("~/Scripts/MicrosoftMvcValidation.js", "~/Scripts/MicrosoftMvcValidation.debug.js");
Html.MvcCssManager().Include("~/Content/Css/Jquery.UI/base/ui.all.css");
%>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Edit</h2>

<% Html.EnableClientValidation(); %>

<% using (Html.BeginForm()) {%>

<fieldset>
<legend>Fields</legend>

<%= Html.EditorForModel() %>

<p>
<input type="submit" value="Save" />
</p>
</fieldset>

<% } %>

<div>
<%=Html.ActionLink("Back to List", "List") %>
</div>

</asp:Content>



So now I'm only referencing script and css hosted on my site but thats for another post...


Feel free to leave comment, I would love to have some feed-back on this.

Saturday, 21 March 2009

Detecting errors in ASP.NET MVC views

That was something annoying with ASP.NET MVC, but there is a simple solution...
this is a copy from ASP.NET MVC - RC Release Notes.



ASP.NET Compiler Post-Build Step

Currently, errors within a view file are not detected until run time. To let you detect these errors at compile time, ASP.NET MVC projects now include an MvcBuildViews property, which is disabled by default. To enable this property, open the project file and set the MvcBuildViews property to true, as shown in the following example:

<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>

Note Enabling this feature adds some overhead to the build time.

You can update projects that were created with previous releases of MVC to include build-time validation of views by performing the following steps:

1. Open the project file in a text editor.

2. Add the following element under the top-most <propertygroup> element:

<MvcBuildViews>true</MvcBuildViews>

3. At the end of the project file, uncomment the <target name="AfterBuild">element and modify it to match the following example:

<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
</Target>