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


By Peter Bromberg
Printer Friendly Version
View My Articles

    

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:

/WebResource.axd?d=PhPk80h_UWEcbheb-NHNP5WshV_47UOpWqAOl1_liUFfN4cNofL74cFlQ1fvpFSf0&t=632573240669964903

-- 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!



Biography - Peter Bromberg
Peter Bromberg is a C# MVP, MCP, and .NET expert who has worked in banking, financial and telephony for over 20 years. Pete focuses exclusively on the .NET Platform, and currently develops SOA and other .NET applications for a Fortune 500 clientele. Peter enjoys producing digital photo collage with Maya,playing jazz flute, the beach, and fine wines. You can view Peter's UnBlog and IttyUrl sites.
Please post questions at forums, not via email!

button
 
Article Discussion: Using the WebResource.axd Handler with Embedded ASP.NET Resources
Peter Bromberg posted at 03-Oct-06 11:18
Original Article

 
Thanks for the artical... I was wondering what the / WebResource.axd?
erik little replied to Peter Bromberg at 03-Oct-06 02:48

syntax was all about..

One question that i have also wanted to know is that why do we have to include the Type parameter when retrieveing a resource..

For example: I create a Webcontrol with just the defalut class and added an image and pretty much followed the artical step by step; but i never actually added the image to the control. I only embedded it into the assambley and added the correct attribute to the assembley.

Below is the one control that i added to my webform so that i could retrieve the resource from the web control assembley.. and all worked great.

Where does the type parameter come into play? Why do i need a typeOf parameter when the image is not even in that type.??

this.Image1.ImageUrl = this.Image1.ImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(myControl.TheControl), "myControl.Mr.C-Stamp.gif");

 

thanks

erik


 
I think the type parameter is required
Peter Bromberg replied to erik little at 03-Oct-06 05:06
so that the Assembly class will know what type to reflect on in order to extract the particular resource. in other words, you are telling it "the image is in myControl.TheControl".

 
Caching is still private
Oleg Ogurok replied to Peter Bromberg at 13-Oct-06 04:03

Hi there.

Thanks for a great article. I'm experiencing no caching of resources. When I run Fiddler, I can see that caching is still Private, and the web resource is requested on every page refresh.

You mentioned that we need to set the mode from Debug to production. I've set the configuration in VS.NET 2005 from Debug to Release but it didn't solve the problem. Is there anything else I need to do?

Thanks,

-Oleg.


 
debug embedded resources
learner plates replied to Peter Bromberg at 01-Nov-06 07:21
Great article.

I've embedded .js files in the assembly using the resource file.
I'm unable to step into the source .js files using the VS debugger, but I am sure the correct assembly and correct resources are being used. What could be preventing me from stepping into the original source files?

 
Yes, you need to have
Peter Bromberg replied to Oleg Ogurok at 24-Jan-07 08:42
debug=false in your web.config. In addition, you cannot test for this by running your project in the Visual Studio IDE debugger!

 
Images embedding on external dll file
Mirta Arambulo replied to Peter Bromberg at 04-Nov-08 11:51
Hi:

I have a great doubt about on how do I to show an image contained in an external dll?

I've just created a external dll (resources.dll) that contains 16000 images as resources. I've included this in my current web project by copying it the bin folder.

By running this:
Assembly dll = Assembly.LoadWithPartialName("resources");
string [] resources = dll.GetManifestResourceNames();
dgPages.DataSource = resources;
dgPages.DataBind();
I got a table listing my images names. So far so good!

But, how do I to show one of these in a img tag?
 <asp:Image ID="imgTest" runat="Server" />
something like this doesn't work:
 imgTest.ImageUrl = resources[1];

Any help well be so appreciated!

Regards

 
This should help
Peter Bromberg replied to Mirta Arambulo at 04-Nov-08 12:16

You essentially are loading images into memory, so you need some sort of handler for the ImageUrl property:

http://www.eggheadcafe.com/articles/20050911.asp


  

Search

search



Purchase