Click here to Skip to main content
15,881,139 members
Articles / Web Development / ASP.NET

JavaScript Organization for MVC

Rate me:
Please Sign up or sign in to vote.
4.80/5 (8 votes)
10 Jan 2011CPOL2 min read 27.5K   32   2
A quick and easy way to organize what script executes for what view.

Introduction

One of my pet peeves is code organization when it comes to putting together an application architecture. I have a current application that is built in ASP.NET MVC 2, using IOC, Dependency Injection, and multiple layers of abstraction from the business layer back.

But I have found that after it was all said and done...there were .js files a plenty for performing all of the UI validation, presentation, AJAX calls, so on and so forth. Most of the scripts were in separate files, but there were also a whole bunch within the Views. Debugging and handing these off the the next developer became a challenge.

The goal was to refactor the organiztion and allow to slowly migrate to a better understanding of what executed where and what part of the script file was responsible for what View. The solution - ScriptViewPage.cs.

ScriptViewPage

The ScriptViewPage class inherits System.Web.Mvc.ViewPage, and when instantiated, adds an event handler for the PreLoad event. So when the View renders, or pre-renders, the event is fired and ScriptViewPage now handles and determines what View is executing and tries to locate the script file that is associated with it.

C#
namespace System.Web.Mvc {     
    public class ScriptViewPage : ViewPage     
    {         
        public ScriptViewPage() 
            : base()         
        { 
                this.PreLoad += new EventHandler(_PreLoad);         
        }

Within the handler, we dig into ViewContext.RouteData to determine the Controller and View and format the .js script file name.

C#
string viewScriptPath = string.Format("~/ViewScripts/{0}/{1}.js", 
                        ViewContext.RouteData.Values["Controller"], 
ViewContext.RouteData.Values["Action"]);

Test to see if the file exists, and using the TagBuilder, create the script tag and set the text of the Literal control on the Master template/View if the control exists.

C#
if (System.IO.File.Exists(MapPath(viewScriptPath)))
{
   var scr = new TagBuilder("script");
   scr.Attributes.Add("type", "text/javascript");
   scr.Attributes.Add("src", ResolveClientUrl(viewScriptPath));

   Control ctrl = Page.Master.FindControl("viewScript");
   if (ctrl != null)
     ((Literal)ctrl).Text = scr.ToString(TagRenderMode.Normal);

}

Here is the complete class code:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace System.Web.Mvc
{
    public class ScriptViewPage : ViewPage
    {
        public ScriptViewPage()
            : base()
        {
            this.PreLoad += new EventHandler(_PreLoad);
        }

        void _PreLoad(object sender, EventArgs e)
        {
            string viewScriptPath = 
              string.Format("~/ViewScripts/{0}/{1}.js", 
              ViewContext.RouteData.Values["Controller"], 
              ViewContext.RouteData.Values["Action"]);

            if (System.IO.File.Exists(MapPath(viewScriptPath)))
            {
                var scr = new TagBuilder("script");
                scr.Attributes.Add("type", "text/javascript");
                scr.Attributes.Add("src", ResolveClientUrl(viewScriptPath));


                Control ctrl = Page.Master.FindControl("viewScript");
                if (ctrl != null)
                    ((Literal)ctrl).Text = scr.ToString(TagRenderMode.Normal);

            }
        }
    }
}

All you need to make sure of is that the .js files are named the same as your Views.

Implementation

I needed a way to slowly refactor the existing code, but also allow for the new script organization to be used for all new View/scripts added to the application. Here is the direction I took.

  • Add a new folder to the root of the Web Application called "ViewScripts".
  • Replicate the folder structure that exists within your "Views" folder.
  • Edit Site.Master and add a Literal control to the bottom of the template above the closing body tag, and set ID="viewScript".
  • In your Views, instead of inheriting from System.Web.Mvc.ViewPage, change it to System.Web.Mvc.ScriptViewPage.

Points of Interest

There may be other ways to accomplish the same task, but this was the easiest method to take in order to not have to restructure the current application and be able to organize and go forward and have a structure to refactor to for existing scripts. Enjoy.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I work on Azure, ASP.NET Core content and Open Source, speak at national and community events while helping teams architect web and cloud applications.

Comments and Discussions

 
GeneralMy vote is 5 Pin
Vitaly Obukhov19-Jan-11 21:57
Vitaly Obukhov19-Jan-11 21:57 
GeneralMy vote of 5 Pin
daltonrs@hotmail.com11-Jan-11 5:07
daltonrs@hotmail.com11-Jan-11 5:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.