11 March, 2011

Registering JavaScripts in your SharePoint/ASP.NET Project

Before going on parental leave I was involved in a fairly large SharePoint project with a distributed team. A question that arose for us was how we should handle script registrations in the solution. With many developers going at it we felt we where in risk of redundant registrations or a registration left out because of miscommunication or faulty assumptions within the team.

Even though we did this in SharePoint I see no reason why it shouldn’t work in a ASP.NET scenario.

Problem statement

How does any given webpart or user control know and ensure that the script it needs is registered on the page.

One possible solution

The solutions is of course many, this is the one I proposed as a solution.

First step is to have a central “repository” of script keys.

public class Keys
{
    public class jQuery
    {
        public static string Version_1_4_4_min = "jquery-1.4.4.min.js";
        public static string Easing_Version_1_3 = "jquery.easing.1.3.js";
        public static string BxSlider_min = "jquery.bxSlider.min.js";
        public static string UI_min = "jquery-ui.min.js";
        public static string Corner = "jquery.corner.js";

    }
}

public class Paths
{
    public class jQuery
    {
        public static string Version_1_4_4_min = "/_layouts/BrandX/js/jquery-1.4.4.min.js";
        public static string Easing_Version_1_3 = "/_layouts/BrandX/js/jquery.easing.1.3.js";
        public static string BxSlider_min = "/_layouts/BrandX/js/jquery.bxSlider.min.js";
        public static string UI_min = "/_layouts/BrandX/js/jquery-ui.min.js";
        public static string Corner = "/_layouts/BrandX/JS/jquery.corner.js";
    }
}
public class ClientScriptService
{
    private static string _scriptTagTemplate
          = " ";

    public static void EnsureClientScript(Page page, string scriptKey, string scriptPath, Type callerType)
    {
        ClientScriptManager scriptManager = page.ClientScript;

        if (scriptManager.IsClientScriptBlockRegistered(scriptKey) == false)  {
            scriptManager.RegisterClientScriptBlock(callerType, scriptKey, string.Format(_scriptTagTemplate, scriptPath));
        }
    }
}

The effect being that each web part ensures its own script dependencies.

protected void Page_Load(object sender, EventArgs e) {
    ClientScriptService.EnsureClientScript(this.Page,
         Scripts.Keys.jQuery.Version_1_4_4,
         Scripts.Paths.jQuery.Version_1_4_4,
         this.GetType());
}

My thought with this was to use it consistently throughout the portal so for example the master page contains a server control registering scripts that is used throughout the portal. For example:

public class MasterPageScriptRegistrations : WebControl
{
    protected override void CreateChildControls() {
        base.CreateChildControls();

        ClientScriptService.EnsureClientScript(this.Page,
            Scripts.Keys.jQuery.Version_1_4_4_min,
            Scripts.Paths.jQuery.Version_1_4_4_min,
            this.GetType());

        ClientScriptService.EnsureClientScript(this.Page,
            Scripts.Keys.jQuery.Easing_Version_1_3,
            Scripts.Paths.jQuery.Easing_Version_1_3,
            this.GetType());

        /* ... */
    }
}

So what do you think? Good/bad? Am I making a hen of a feather? I really appreciate feedback (either here in the comments or by email to niklas.nihlen[at]gmail.com).


Tags: ,