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.