Using Embedded Resources for Client Script Blocks in ASP.NET

A while ago Patrick Cauldwell highlighted a wonderful technique of using embedded resources for unit testing with external files.

Fully on board with Pat, I’ve applied that technique to client script blocks when building web controls and ASP.NET pages.

How often have you written (or had to deal with) crap like this.

string script = "<script language=\"javascript\">"
  + "function SomeFunction(someParam)" + Environment.NewLine
  + "{" + Environment.NewLine
  + "    alert(’Man, this sucks!’);" + Environment.NewLine
  + "}" + Environment.NewLine
  + "</script>";

A preferred approach is to have your client script code in a separate file. For web controls, I generally have a folder named Resources that contains a folder named Scripts. I’ll add my client script files there as embedded resources. In figure 1 below, you can see that I have two script files in my project.

Embedded Scripts
Figure 1 Script files.

To make sure these files are compiled as embedded resources, I select the files and set the build action to embedded resource in the Properties window as in figure 2.

Embedded Resource
Figure 2 Build Action = Embedded Resource.

Now when I need to display these scripts in a page, I can use the following code which makes use of my handy dandy ScriptHelper class.

if(!Page.IsClientScriptBlockRegistered("PairedDropDownHandler"))
{
  string script = ScriptHelper.UnpackScript("PairedDropDown.js");
  Page.RegisterClientScriptBlock("PairedDropDownHandler", script);
}

The contents of my embedded script files do not contain the <script> tags. I leave that responsibility to my ScriptHelper class so that these script files can be used as stand alone script files as well. The code for my script helper class is below.

/// <summary>
/// Utility class for extracting embedded scripts.
/// </summary>
/// <remarks>
/// Uses a naming convention. All scripts should be placed 
/// in the Resources\Scripts folder. The scriptName is just 
/// the filename of the script.
/// </remarks>
public static class ScriptHelper
{
  /// <summary>
  /// Returns the contents of the embedded script as
  /// a stringwrapped with the start / end script tags.
  /// </summary>
  /// <param name="scriptName">FileName of the script.</param>
  /// <returns>Contents of the script.</returns>
  public static string UnpackScript(string scriptName)
  {
    string language = "javascript";
    string extension = Path.GetExtension(scriptName);
  
    if(0 == string.Compare(extension, ".vbs", true
      , CultureInfo.InvariantCulture))
    {
      language = "vbscript";
    }
        
    return UnpackScript(scriptName, language);
  }

  public static string UnpackScript(string scriptName, string scriptLanguage)
  {
    return "<script language=\"Javascript\">"
      + Environment.NewLine
      + UnpackEmbeddedResourceToString("Resources.Scripts." + scriptName)
      + Environment.NewLine
      + "</script>";
  }
 
  // Unpacks the embedded resource to string.
  static string UnpackEmbeddedResourceToString(string resourceName)
  {
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    Stream resourceStream = executingAssembly
      .GetManifestResourceStream(typeof(ScriptHelper), resourceName);
    using(StreamReader reader = new StreamReader(resourceStream, Encoding.ASCII))
    {
      return reader.ReadToEnd();
    }
  }
}

You’ll be seeing this ScriptHelper class again when I highlight some controls you might find useful. If you’re already using ASP.NET 2.0 (aka Whidbey), there’s an even better way to handle client files.

UPDATE: I just realized I was using code from a StringHelper class I wrote. I updated that bit to inline the simple functionality.

Technorati tags:

What others have said

Requesting Gravatar... Steven Campbell May 02, 2005 7:13 AM
# re: Using Embedded Resources for Client Script Blocks in ASP.NET
This is great, but I would simplify it even further by creating a method that accepts the Page object as a parameter, so it can be used in one line, like:
ScriptHelper.IncludeScript("PairedDropDownHandler", "PairedDropDown.js", Page)

or maybe even just

ScriptHelper.IncludeScript("PairedDropDown.js", Page)

(defaulting the name of the script block somehow)
Requesting Gravatar... Scott May 03, 2005 7:45 AM
# re: Using Embedded Resources for Client Script Blocks in ASP.NET
This is great as long as you have a small script and no bandwidth requirements. If you have a large piece of javascript, it's often better to reference it using the "src" attribute of the script tag and place it in the path. That way the client browser will download it once and then cache it. Otherwise you end up sending the same script down every time the page loads.

Of course I'm talking about script files that are measured in K not chars<grin>. If the scripts is really small, then it's better to embed it in a resource file (even though the resource editor in VS 2003 really sucks). Makes the drag and drop deployment of web controls a reality! I've been working on a way to embed the images into a web control assembly and stream them to the client at runtime. I haven't come up with a satisfactory solution yet.
Requesting Gravatar... haacked May 03, 2005 8:24 AM
# re: Using Embedded Resources for Client Script Blocks in ASP.NET
VS.NET 2005 handles that with WebResource.axd I believe. I am planning to tackle that issue as well, though it's lower priority.

In the meantime, you should take a look at Fritz Onion's dynamic image control.
http://pluralsight.com/blogs/fritz/archive/2005/02/11/5789.aspx
Requesting Gravatar... Ramesh Jun 29, 2006 12:06 AM
# re: Using Embedded Resources for Client Script Blocks in ASP.NET
This is great. But i would like to hide my script from client. but your script helper shows the script in the client.

If any other way is there please post it.
Requesting Gravatar... Michael Freidgeim Aug 04, 2006 5:19 AM
# re: Using Embedded Resources for Client Script Blocks in ASP.NET
Your UnpackScript(string scriptName, string scriptLanguage) doesn't use scriptLanguage,but hardcoded it to Javascript
Requesting Gravatar... james nnannah Feb 16, 2008 10:20 AM
# re: Using Embedded Resources for Client Script Blocks in ASP.NET
For reasons I cannot fathom, I cannot access the 'build action' property for files or resources included in my project. I am using vs2005 (asp.net 2.0).
Requesting Gravatar... Samir Nigam Mar 15, 2008 2:55 AM
# re: Using Embedded Resources for Client Script Blocks in ASP.NET
Is it possible to modify content of a embadded resource file?

What do you have to say?

(will show your gravatar)
Please add 3 and 2 and type the answer here: