Click here to Skip to main content
Click here to Skip to main content
Go to top

JavaScript Organization for MVC

, 10 Jan 2011
Rate this:
Please Sign up or sign in to vote.
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.

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.

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.

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:

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)

Share

About the Author

Shayne P Boyer
Architect Boyer Consulting Services
United States United States
Shayne Boyer aka TattooCoder, has been developing Microsoft based solutions for the last 15 years. Currently working as a Solutions Architect focused on Services Oriented Architecture and in his spare time runs the Orlando Windows Phone and Windows 8 User Group. He is a passionate developer and loves to talk about his craft, teach and also learn from others.
 
- MCSD .NET
- Telerik MVP
- Orlando Windows Phone & Metro User Group Founder (@OrlandoWPUG)
- INETA Speaker
- DZone.com MVB
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote is 5 PinmemberVetalRMP19-Jan-11 21:57 
GeneralMy vote of 5 Pinmemberdaltonrs@hotmail.com11-Jan-11 5:07 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140922.1 | Last Updated 10 Jan 2011
Article Copyright 2011 by Shayne P Boyer
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid