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.
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:
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:
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).
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!