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

JavaScript Extension Methods

, 17 Jul 2008
Rate this:
Please Sign up or sign in to vote.
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:

[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:

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:

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.

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:

<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!

//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:

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)

Share

About the Author

MaxSchmeling
Software Developer Leggett and Platt
United States United States
I have roughly six years (more if I've forgotten to update this in a while :P) of experience in software development.
 
The majority of my experience in the "real world" of software development has been on internal enterprise development teams.
 
I have a passion for development and I believe in doing things the right way. To sum it all up: I'm an ALT.Net member.

Comments and Discussions

 
GeneralinsertAudio Pinmemberwwwyfjp19-Jul-08 21:07 
GeneralinsertInamge Pinmemberwwwyfjp19-Jul-08 21:06 
GeneralEditor Pinmemberwwwyfjp19-Jul-08 21:05 
QuestionHow is this different to System.Web.UI.ScriptResourceAttribute? Pinmemberleppie17-Jul-08 21:39 
From what I can see, it is the same.
 
xacc.ide - now with TabsToSpaces support
AnswerRe: How is this different to System.Web.UI.ScriptResourceAttribute? PinmemberMaxSchmeling18-Jul-08 5:49 

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 17 Jul 2008
Article Copyright 2008 by MaxSchmeling
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid