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.
No comments:
Post a Comment