JavaScript script per page in ASP.NET MVC

In ASP.NET MVC the views can get pretty big pretty quick, so i think anything you can do to keep them lean is worth trying. I wanted to come up with a way of allowing javascript for a view page to be held in its own a separate script file, and be served only it it exists.

I wanted to have the script file sit alongside with the same name (apart from extension) as the view, and be served from this location; I thought this would be a nice convention, and from a glance it would be possible to see which views had scripts. The following is a less abstracted (ie: shorter and easier to write up) version of what I came up with, but should be more than enough info to show how it can be done…

By default the Views sub folder web.config file blocks any request for resources as MVC does not serve pages. The first change required is to amend this to block requests for *.aspx and serve *.js using the System.Web.StaticFileHandler. Something like the following from the httpHandlers section (remembering this will also need to be done in the system.webServer handlers section for IIS7 in integrated mode:

<httpHandlers>
	<add path="*.aspx" verb="*" type="System.Web.HttpNotFoundHandler"/>
	<add verb="GET,HEAD" path="*.js" type="System.Web.StaticFileHandler"/>
</httpHandlers>

In the solution I already had a base class for the site master page. The following code was added to the OnPreRender for the site master base:

string scriptPath = Page.AppRelativeVirtualPath.Replace(".aspx", ".js");
if (HostingEnvironment.VirtualPathProvider.FileExists(scriptPath))
    Page.Header.AddScript(scriptPath);

It gets the script path from the current page virtual path (replacing aspx with js to locate the views script file along side), then using the VirtualPathProvider from the HostingEnvironment adds a script ref to the header if the script file exists. Note that the AddScript is a simple extension method on HtmlHead:

public static void AddScript(this HtmlHead head, string src)
{
    HtmlGenericControl script = new HtmlGenericControl { TagName = "script" };
    script.Attributes.Add("type", "text/javascript");
    script.Attributes.Add("src", head.Page.ResolveClientUrl(src));
    head.Controls.Add(script);
    head.Controls.Add(new LiteralControl("\n"));
}

that will just render a script tag in the header for the supplied script src.

So you end up being able to place your js files as you require alongside the view, and keep all the page specific javascript (and lovely jQuery) stuff out of the view and in its own file.

Comments are closed