Using the WebResource.axd Handler with Embedded ASP.NET Resources

Shows the use of the WebResource.axd handler in ASP.NET 2.0 and covers a couple of "gotchas".

Last May, I did an article that explored how to "Retrofit" the new WebResource.axd features in ASP.NET 2.0 and how you could "replicate" all the features of the 2.0 ClientScript callback into the 1.1 platform.

Here I want to focus on one aspect of the items covered there, and that is the use of the WebResource.axd "phantom handler" that's built into 2.0 to enable ASP.NET pages, controls (and developers) to inject assets into the client-side Page DOM.

First, let's define "embedded resource": An embedded resource is any file (Image, Javascript, CSS, you name it) - that has been included in a project and marked "Embedded Resource" by right-clicking the object and selecting that entry from the "Build Action" dropdown in the Properties Sheet for the object. What this does is tell the compiler to include the object in the assembly. If you want, you can fire up Reflector on one of your assemblies that contains an embedded resource and get a much clearer picture of how and where in the assembly this is done.

In ASP.NET 1.1, you can use the Assembly class method GetManifestResourceStream to pull out any object that has been embedded in this manner, process the stream result, and do whatever is appropriate with it --- you can set the Response ContentType header to tell the browser what to expect, and write it to the Response Output stream. However, in ASP.NET 1.1 there is no "built-in" way to do this external to your assembly - you have to do it programmatically.  If you had doubts about the naming conventions of your embedded resources, you could use the GetManifestResourceNames method, which returns a string array of the exact full name of each resource in the assembly.

ASP.NET 2.0 provides the WebResource.axd handler that allows an external request using this "axd" extension (works the same way the Trace handler works) to retrieve these embedded resources with a standardized HTTP Request URI in the format: http://site/WebResource.axd?d=assemblyKey&t=LastAssemblyWriteDatetime. The handler type for WebResource.axd is AssemblyResourceLoader.

This feature is not enabled by default, however. It gets "enabled" by adding an entry into the AssemblyInfo.cs (vb) File:

[assembly: WebResourceAttribute("MyNameSpace.Resources.MyImage.gif", "image/gif")]

"MyNameSpace" above, is the default namespace indicated in the project properties. "Resources" is the folder in the project where the embedded resource resides. If it is not in a subfolder, you would leave this out. Finally, "MyImage.gif" is the actual file name of the resource, with "image/gif" being the MIME type of the embedded resource. You will need a "using" or "Import" directive for System.Web.UI, which is where WebResourceAttribute lives.

There is an overload to the attribute declaration that has the additional boolean parameter "performSubstitution". What this does (when "true") is to determine whether other Web Resource URLs that are referenced in this resource are parsed and replaced with the full path of the resource. You might use this feature if you had a CSS file embedded and it referenced an image file as a background image.

For example, you could have a client-side script function like so:

function ChangeImage(imgControl,varcolor)
document.getElementById(imgControl).src = '<%= WebResource("MyControl.MyImage.gif")%>'; document.getElementById('Label1').style.color = varcolor;

Note the markup above. In place of the image URL we use the special syntax - WebResource(FullNameOfResource). This is a kind of placeholder for the resource and ASP.NET will then replace it with the actual URL at runtime.


With this addition complete, a call to:

Page.ClientScript.GetWebResourceUrl(typeof(MyNameSpace.MyControl), "MyNameSpace.Resources.MyImage.gif")

would result in delivery of the embedded resource in control "MyControl" via an axd request url that would look like this:


-- where ?d= is the Assembly Key, and t= is the lastwritetime of the compiled assembly (used for versioning).

For javascript files, the technique is the same except your MIME type would be "text/javascript".

Incidentally, in ASP.NET 2.0 all validation scripts are processed via this server-side handler . Http compression prevents WebResource.axd client side scripts from rendering normally. Excluding the path=WebResource.axd from the compression configuration solves this problem. This particular HttpCompression Module at Gotdotnet workspaces will correctly compress WebResource.axd accessed resources.

You might be wondering about caching. When your assembly is compiled in debug mode, the caching is private (that means no caching) but while compiled in production mode, it will be public. So, don't worry -- you will get the advantage of caching on these embedded resources in production!

By Peter Bromberg   Popularity  (17755 Views)