Click here to Skip to main content
15,867,330 members
Articles / Web Development / HTML
Article

JavaScript Extension Methods

Rate me:
Please Sign up or sign in to vote.
3.67/5 (2 votes)
17 Jul 2008CPOL2 min read 78.6K   111   19   5
A set of extension methods for dealing with JavaScript files in ASP.NET.

Introduction

The purpose of this code is to make working with JavaScript files in ASP.NET easier and "cleaner". The JavaScriptFileHelper class contains several extension methods that look for the JavaScriptFileAttribute on a System.Web.Page or System.Web.MasterPage, and then it includes the files specified by each JavaScriptFileAttribute.

Background

This code is one of the first things I wrote when I started using ASP.NET 3.5. I've had it laying around for a while now, and thought maybe somebody else could benefit from it.

This is not intended to be any kind of overall JavaScript helper framework. The intention with this code is to provide a declarative means of including JavaScript files with an ASP.NET page.

I do realize that you can easily just put the script tag in the ASPX page, but I like this better. It's quicker, easier to remember, and cleaner. I think it makes a good addition to my common library.

Using the Code

The code is extremely simple to use. Once you have the two classes in your project, or in a referenced assembly, you only have to do two things. First, you have to decorate the page(s) that you want a JavaScript file included on with a JavaScriptFileAttribute, as shown here:

C#
[JavaScriptFile("/scripts/util.js")]
public class _Default : System.Web.Page
{
   //code goes here
}

The string "/scripts/util.js" is the path (can be a relative path) to the JavaScript file. This string just gets stored in the Path property of the JavaScriptFileAttribute, which is shown here:

C#
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;

namespace Your.Namespace.Here
{
   [AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=true)]
   public class JavaScriptFileAttribute : Attribute
   {
     public string Path { get; private set; }

     public JavaScriptFileAttribute(string path)
     {
        this.Path = path;
     }
   }
}

The second thing you have to do is make a call to one of the extension methods in JavaScriptFileHelper to make it examine the page, master page, or user control, and include the files. Here is an example of how to do that:

C#
public class _Default : System.Web.Page
{
   public override void OnLoad(EventArgs e)
   {
      base.OnLoad(e);

      this.RegisterJavaScriptFiles();
   }
}

I've included the extension method class here for your convenience. All this code really does is find the page object, and then makes a call to its ClientScriptManager's RegisterClientScriptInclude method.

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

namespace Your.Namespace.Here
{
   public static class JavaScriptFileHelper
   {
      public static void RegisterJavaScriptFile(this MasterPage masterPage, string path)
      {
         JavaScriptFileHelper.RegisterJavaScriptFile(masterPage.Page, path);
      }

      public static void RegisterJavaScriptFile(this Page page, string path)
      {
         JavaScriptFileHelper.RegisterJavaScriptFile(page.ClientScript, path);
      }

      public static void RegisterJavaScriptFiles(this MasterPage masterPage)
      {
         JavaScriptFileHelper.RegisterJavaScriptFiles(masterPage.GetType(), 
                                             masterPage.Page.ClientScript);

         if (masterPage.Master != null)
         {
             JavaScriptFileHelper.RegisterJavaScriptFiles(masterPage.Master);
         }
      }

      public static void RegisterJavaScriptFiles(this Page page)
      {
         JavaScriptFileHelper.RegisterJavaScriptFiles(page.GetType(), page.ClientScript);

         if (page.Master != null)
         {
            JavaScriptFileHelper.RegisterJavaScriptFiles(page.Master);
         }
      }

      public static void RegisterJavaScriptFile(this UserControl userControl, string path)
      {
         JavaScriptFileHelper.RegisterJavaScriptFile(userControl.Page.ClientScript, path);
      }

      public static void RegisterJavaScriptFiles(this UserControl userControl)
      {
         JavaScriptFileHelper.RegisterJavaScriptFiles(userControl.GetType(), 
                                             userControl.Page.ClientScript);
      }

      private static void RegisterJavaScriptFiles(Type type, ClientScriptManager manager)
      {
         IEnumerable<JavaScriptFileAttribute> attributes = type.GetCustomAttributes(
             typeof(JavaScriptFileAttribute), true).Cast<JavaScriptFileAttribute>();

         foreach (string path in attributes.Select(o => o.Path))
         {
            JavaScriptFileHelper.RegisterJavaScriptFile(manager, path);
         }
      }

      private static void RegisterJavaScriptFile(ClientScriptManager manager, string path)
      {
         //no need to register it twice
         if (!manager.IsClientScriptIncludeRegistered(path))
         {
            manager.RegisterClientScriptInclude(path, path);
         }
      }
   }
}

The end result of all of this (when adding "/scripts/util.js") is the following line of code in the page:

HTML
<script src="/scripts/util.js" type="text/javascript"></script>

Points of Interest

What I did in the web application project that I created this for is create base page, MasterPage, and the UserControl implementations that all call this.RegisterJavaScriptFiles() in their OnLoad override. Using these base classes, all that needs to be done is the attribute decoration. The register call is hidden away in the base class so that it doesn't clutter up the derived class. I've also got a "common library" of JavaScript files that are used on most pages, which I've put on the base master page. This way, those files are *always* available to me without any extra work.

Unrelated to the purpose of this write-up - Automatic Properties are awesome!

C#
//this single line...
public string Path { get; private set; }

//replaces all of this
private string path;

public string Path
{ 
   get { return this.path; }
}

And also, working with attributes is much cleaner now. In 2.0, the code would have been pretty "ugly" to pull the Path values, but in .NET 3.5, it only takes this:

C#
IEnumerable<JavaScriptFileAttribute> attributes = type.GetCustomAttributes(
    typeof(JavaScriptFileAttribute), true).Cast<JavaScriptFileAttribute>();

foreach (string path in attributes.Select(o => o.Path))
{
   //code here
}

History

  • Published article (7/17/08).

License

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



Comments and Discussions

 
GeneralinsertAudio Pin
wwwyfjp19-Jul-08 21:07
wwwyfjp19-Jul-08 21:07 
GeneralinsertInamge Pin
wwwyfjp19-Jul-08 21:06
wwwyfjp19-Jul-08 21:06 
GeneralEditor Pin
wwwyfjp19-Jul-08 21:05
wwwyfjp19-Jul-08 21:05 
QuestionHow is this different to System.Web.UI.ScriptResourceAttribute? Pin
leppie17-Jul-08 21:39
leppie17-Jul-08 21:39 
AnswerRe: How is this different to System.Web.UI.ScriptResourceAttribute? Pin
User 242725618-Jul-08 5:49
User 242725618-Jul-08 5:49 

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.