Registering scripts into the page header with ASP.NET 2.0

UPDATE 19/08/2006: changed the API, no more public constructor but static property to access the instance of the HeadScriptManager.
UPDATE 03/08/2006: now the library allows to register stylesheets too. See class diagram below for details.

ASP.NET 2.0 pages expose a new property called ClientScript of type ClientScriptManager, which allows to manage client-side scripts, usually Javascript but not just that. Its public methods allow to render scripts in different parts of the page, as well as to register some client-side events.
In particular, scripts can be rendered just below the opening of the form tag or just before its closing, but it's not directly possible to include scripts into the head tag.
With ASP.NET 2.0 you may have noticed that web forms created with Visual Studio 2005 and family products automatically place the runat="server" attribute in the head tag of each page. That's why the Page class exposes a new property called Header, of type HtmlHead, which allows to interact with the page header and do something like including an external script:
HtmlGenericControl Include = new HtmlGenericControl("script");
Include.Attributes.Add("type", "text/javascript");
Include.Attributes.Add("src", "http://dev.virtualearth.net/mapcontrol/v3/mapcontrol.js");
this.Page.Header.Controls.Add(Include);
or like injecting code manually:
HtmlGenericControl Include2 = new HtmlGenericControl("script");
Include2.Attributes.Add("type", "text/javascript");
Include2.InnerHtml = "alert('JavaScript in Page Header');";
this.Page.Header.Controls.Add(Include2);
Looking at this post by Christopher Pietschmann (where I shamelessly got the above code) I had the idea of creating a library to extend the features of the ClientScriptManager class to the header of the page. Unluckily that class is sealed, it would have been nice to create a partial class to extend it... I always wonder why the guys at Microsoft don't let us exploit the power of the framework exposing some more of their internal, private, and sealed stuff. However what I came up with - thanks to Reflector to keep the API close to that exposed by the framework as well as to save time - is a simple class which can be used in the same way, and lets you render script blocks, script includes and embedded resources in the page header. To be more user-friendly it keeps the member names of its "parent" class. Here is the diagram:



UPDATE 03/08/2006: the class exposes a new set of methods with a similar signature which allow to inject stylesheets. The usage is the same, but they render the content inside <style> tags in case of embedded styles (RegisterHeadStyleBlock) or inside <link> tags in case of linked styles (RegisterHeadStyleInclude and RegisterHeadStyleResource). It comes useful mostly to control developers, so that you can inject embedded assembly resources.
UPDATE 19/08/2006: the API has changed and the constructor is not directly accessible. The instance of the HeadScriptManager can be accessed using the Current static property. The example below has been updated to reflect this change.

Now it can be used referencing the assembly in the project, creating an instance and calling its methods:
HeadScriptManager manager = HeadScriptManager.Current;

manager.RegisterHeadScriptBlock(this.GetType(), "scriptKey", "alert('hello');", true);
Source and binaries are available along with my main project, BusyBoxDotNet.

kick it on DotNetKicks.com

Published 29 July 2006 12:09 AM by simoneb
Filed under: ,

Comments

# DotNetKicks.com said on 28 July, 2006 08:21 PM
You've been kicked (a good thing) - Trackback from DotNetKicks.com
# Michal Talaga said on 02 August, 2006 10:28 AM
You may also be interested in my article about putting ContentPlaceHolder inside the head element of master page:
http://mikeoff.blogspot.com/2006/07/master-page-contentplaceholder-inside.html
# simoneb said on 02 August, 2006 10:39 AM
Thanks Michal, my solution is optimal for control developers, where you don't have any declarative interaction with the page, but I knew about the head contentplaceholder, it's a nice feature.
# Chris Pietschmann said on 04 August, 2006 03:52 PM
Nice wrapper class around this functionality.
# simoneb said on 04 August, 2006 04:12 PM
Thanks Chris, Reflector helped a lot ;)
# LarryS said on 11 December, 2006 10:53 PM
Thanks for the code. For my own use, I added an additional overload: RegisterHeadStyleInclude(Type type, string key, string url, string media) The "media" attribute of the link tag allows you to specify stylesheets for "all", "print", etc. Useful for custom print-only stylesheets.
# simoneb said on 14 December, 2006 06:43 PM

Thanks Larry, I'd be grateful if you could create a patch so that I can merge the changes in my code. You can find the repository here: http://sourceforge.net/projects/busybox

# Craig said on 15 January, 2007 03:53 PM
First, thanks for the great work! This is exactly what I'm looking for. Second, what is the licensing on this? Is this public domain? Thanks again!
# simoneb said on 15 January, 2007 07:03 PM

No restrictions, feel free to use this code as you wish.

# sinful monk said on 13 February, 2007 10:04 PM
Excellent work!!! I've updated 100+ pages in my app with this HeadScriptManager.
# SimoneB's Blog said on 16 April, 2007 08:12 PM

A while ago I blogged about a pattern useful to ensure that just a single instance of a class was created

# blogging developer said on 02 September, 2007 03:04 PM

I prepared a blog post about the HeadScriptManager. You may read the post at: HeadScriptManager - A class library for registering scripts into the page header with ASP.NET 2.0

Cheers

This site

Search

Go

This Blog

News

Syndication

Sponsors

  • MaximumASP