Jesse questions the reasons behind this attribute, and that gives me a reason to blog...
For those who haven't seen this attribute, its an assembly-level metadata attribute that allows server control developers to mark embedded resources as URL-accessible, and ties in with the "Web Resources" feature introduced in ASP.NET "Whidbey". Briefly said, Web resources allow control developers to package up client files such as scripts, images, style sheets etc. and use them in the generated rendering simply by embedding them into the assembly, rather than having to scatter them into the file system (such as in the aspnet_client folder). More manageable, cleaner, and simpler deployment!
One reason for this attribute is security. Without the attribute, any embedded resource in any assembly (from GAC or bin) would be automatically URL-accessible. Admittedly, there might not be many security concerns exposing a script file or an image file, but conceptually, its not exactly what you want. Also, the framework that we create now cannot guess what resources (or what assemblies) may appear down the road, and therefore we placed the restriction of requiring Web resources to be explicitely marked upfront (remember adding restrictions down the road is a breaking-change).
Another reason for the attribute is to be able to specify content type. As Jesse mentioned, the content type could be derived from the file name (note to self: Look into making the content type optional). However, we'd like to give the control developer the option of specifying content type, and therefore created a mechanism to do so without depending on a mapping registered elsewhere on the system.
Final reason for the attribute: Extensibility. Basically the ability to specify additional metadata about the resource is interesting. Again, we're putting a system in place that allows us to do cool things now, and more in the future. For an example of a cool trick, read on...
Using Web Resources
Imagine I am writing an HtmlEditor control and I want to use a stock bold button icon. Here's what I'd do:
-
Embed "Bold.gif" as a resource with the same name into my control's assembly.
-
Mark it as Web-accessible via the attribute:
[assembly: WebResource("Bold.gif", ContentType.ImageGif)]
-
Use the GetWebResourceUrl() method on Page to get a URL that can be rendered out to the client.
boldButton.ImageUrl = Page.GetWebResourceUrl(typeof(HtmlEditor), "Bold.gif");
This results in a URL of the form:
WebResource.axd?a=MyControls&r=Bold.gif&t=632059604175183419
The "a" and "r" query string parameters stand for the assembly and resource names respectively. I'll get to the foofy-looking "t" parameter in a moment.
One rather nice fallout of Web resources is that you automatically benefit from resource localization. If I had a satellite resource assembly with a resource named "Bold.gif", then that would be served up, and not the culture-neutral one. Works great if you've got images or error messages in script files that are culture sensitive.
Perf?
Early on, when we first prototyped this feature, there was concern about perf when using Web resources. Imagine hitting the Web server once per Web resource. With a large number of pages using the WebForms.js script file packaged as a resource, we'd be processing two requests for each page. Ack!
So, what we did was set the appropriate cache headers, so that a) the browser would indefinitely cache it, and not even issue a request to check if the content was updated and b) we use output cache on the server (which automatically uses disk output cache also added in Whidbey). The downside was that the development experience wasn't great. Each time I'd change, WebForms.js, I'd have to flush out the cache to pick up the changes. That's where the the "t" parameter comes in. Its basically an assembly timestamp. When the assembly is re-built, the rendered URL contains a different "t" parameter value, and the browser does make a request and picks up the updated content. Otherwise, the same "t" value keeps getting rendered, and the browser's (or the server) cache is used.
And finally, a cool trick...
Imagine that I writing a WebPart control that ships with its own help file embedded as a resource (each WebPart can offer up a Help URL). The help page I want to serve up contains my logo image, and I'd like to embed the image as a resource as well. However, theres no way to statically specify the src attribute of the image inside the .htm embedded resource. Enter WebResourceAttribute.
[assembly: WebResource("Help.htm", "text/html", /*
performSubstitution */ true)]
The third parameter tells the framework that this resource contains macros that need to be substituted in with real values dynamically. In Help.htm, I'd have the following:
<img src="<%= WebResource(Logo.gif) %>" />
Voila! Now, if you look at the served up Help.htm file, you'd see the image pointing at another WebResource.axd URL. For now, "WebResource()" is the only thing you can place inside the <%= %> syntax within an embedded resource, but perhaps there would be something more in the future. Cool huh?
Posted on Tuesday, 12/2/2003 @ 5:08 PM
| #
ASP.NET