Introduction

This code drop is part of Redux series. This article started out to be about a dropdown date/time ASP.NET 2.0 server control. So I built the control and all its ancillary JavaScript, along with the images, and then everything was put into a zip file for uploading to the CodeProject. The installation instructions for the control went something like this:

Unzip the contents to a folder.

Copy the DLL to the Bin folder of your new project.

Copy the JavaScript file.

Copy the CSS file.

Copy the images.

Hey, wait a minute, this is really lame, why all the extra files, why not embed them into the DLL as resources. That was the beginning of three days of hell trying to understand and work with WebResources. I have boiled it down to about twenty lines of working code.

Nothing else on the net gives you an actual working sample and a lot of the information is simply wrong (possibly because it was based on beta versions). Well, this code compiles and runs on the release version of .NET 2.0.

Code snippets

Create a project which looks like this (you can get the control from the download and then just add an ASP.NET project to the solution):

Highlight the three files in MyResources, and in the Properties window, set Build Action to Embedded Resource:

This is not a discussion on server controls, so let's focus on the parameters of GetWebResourceUrl:

this.GetType() - mandatory, just do it.

"MyWebResourceProj.MyResources.Test.js" - this is the most misunderstood parameter and the source of just about all errors. It is composed of [Assembly of this project].[Folder containing resource].[Filename of resource].

No matter what you read anywhere else, including Microsoft's official documentation (which is wrong), if you don't do it this way, you will fail (I know this from personal experience).

You need to specify the resource name exactly as you did in your program code. You need to specify the mime-type. If the file contains JavaScript, you may want to have ASP.NET perform text substitution. For example, you may have a line in JavaScript like:

document.write("<img src='Test.gif'>");

When you embed your images in a resource, you no longer know the name of it as it appears in the resource. To fix this, code as follows:

All the "official documentation" and all the articles on the web say that you can leave [AssemblyName].[FolderName] out. But they are dead wrong!

Note: if you are using this control as the base class of another, see yc4king's note below.

Update

KonstantinG has pointed out an error which only becomes apparent when your namespace is not the same as your assembly name. Previously, I had indicated that the name of the resource is: [Namespace of this project].[Folder containing resource].[Filename of resource], but really it is [Assembly of this project].[Folder containing resource].[Filename of resource]. As always, the best way to find information on this is by using Lutz Roeder's .NET Reflector available at aisto.com.

SmashGrab / Redux series

I have recently started two series of articles here at CodeProject.

Smash and Grab is intended as a series of short articles on one specific code technique. Redux is intended as a series of longer articles which attempts to reduce a complicated topic (like WebResource) into its basic constituent parts and show that once you have all the information, it isn't really that hard. To find the Smash and Grab articles, search for the keyword SmashGrab. To find the Redux articles, search for the keyword Redux. I welcome any contributions to either series, but please follow the guidelines when submitting articles to either.

Conclusion

So there you have it, everything you need to know to use WebResources. This article documented how to place CSS files in the <head> section, extract JavaScript files, dynamically change the contents of a JavaScript file.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

I have a control named 'CustomGrid' in an assembly named 'MyAssembly1'. This custom grid uses embedded resources (css, images) which is setup in MyAssembly1.AssemblyInfo.cs. The customGrid works perfectly.

I created another assembly named 'MyAssembly2' with a control named 'SuperGrid' that inherits from 'MyAssembly1.CustomGrid'. When I add SuperGrid to my application, the css and images do not work. What do I need to do to make this work?

from my experience it is not [AssemblyName].[FolderName] but [Namespace].[FolderName] in my project they are different and when using reflector on my dll with the embedded resource I see the resource with [Namespace].[FolderName] alse when I call RegisterClientScriptResource i have to use Namespace otherwhise my jscript file is empty

Agreed, it doesn't seem to be the Assembly Name, but the Default Namespace in the properties that is what's used. In most cases, these are probably the same, so that's why it's not a big deal for most people.

You did it!! man I must have read half a dozen articles on the internet, and none of it worked for me. Yours had the difference of explaining how the assembly info tag should exactly be and that worked.... thanks a lot buddy, keep up the good work!!

After 2 days of scavenging the web for info on the topic of RegisterClientScriptResource and RegisterClientScriptInclude I am doing the rounds and sharing what I discovered with the people that posted on the same topic:

RegisterClientScriptInclude will not work unless your page has a <form runat='server"> somewhere.

Hope this helps all the people having problems with these new APIs,/cheer

This fails, because of "GetType()" is not applicable in this context. The same works fine on System.Web.UI.Page, but trying to use it with System.Web.UI.MasterPage fails. What should I use as the first parameter of GetWebResourceUrl()?

I have found that using typeof expression provides more accurate results over GetType, especially when using masterpages. Try typeof(MyClassName) where MyClassName is the class that your GetWebResourceUrl method is contained.

[ToolboxData("<{0}:MyWebResource runat=server></{0}:MyWebResource>"), ToolboxBitmap(typeof(MyWebResource), "MyWebResourceProj.MyResources.Test.gif")] public class MyWebResource : System.Web.UI.WebControls.TextBox {..}suppose if i add bitmap type what type i have to specify at mime type?

I have been trying to use a self-composed date-picker server control (mostly made up of a lot of client code through embedded js). I added the control as the edit control in a Template Field to use it on a form wrapped in an Ajax panel. I then discovered that under Ajax, the logic of adding resources becomes a little harder, as you may be requesting to populate the form with new controls in a callback.

The form (DetailsView) is default read only and renders only label controls. Clicking Modify, the ajax call replaces the controls with input controls of various kinds through their respective Field Templates. This works for all controls besides my control, as it is attempting to attach the css required by the javascript calendar.

Image files and js files are embedded as expected, but the css is a huge problem.In my first attempt, the javascript would call and render the styles into the page using a js document.write method attached with RegisterClientScriptBlock. However, when this happened during a callback, ajax would simply not comply. IE just rendered the control without styles, while FF simply hung.

I secondly tried your way of splitting off the css into a resource file and then attaching it as a linked resource in the header during the control's OnInit. But again, as long as this is attempted done in a callback, there is no way Atlas is able to do the job. I am now wondering how many controls out there will suffer the same fate?

KonstantinG has pointed out an error which only becomes apparent when your namespace is not the same as your assembly name. Previously, I had indicated that the name of the resource is: [Namespace of this project].[Folder containing resource].[Filename of resource], but really it is [Assembly of this project].[Folder containing resource].[Filename of resource].

This may be correct in your case, but it sure didn't work for me.

I had the resources in a subdirectory 'Resources' which was created at the root of the project. However, I had to use the [Namespace].[filename] in the assemblyinfo.vb as well as in the code to get the url reference. Somehow, when I replace [Namespace] with [AssemblyName] it didn't work and also putting the directory 'Resources' in between caused failure.

I downloaded the source of this article to experiment with because I was having problems getting it to work in a project I'm working on. Although this source works as is, I found that by making it so the namespace is different from the assembly, it does not work. Referring to the resource using either assembly name or namespace didn't work.

I have found that in order to reference the resource using the assembly name (which makes more sense to me than using the namespace) while the namespace and assembly name are different, you must open the Properties of each resource and set the "Build Action" to "Embedded Resources". Voila! Now it works exactly as described in this article even when the namespace and assembly name are different.

I was wrong! When I got it to work, my assembly name and Default Namespace in the Properties of the project were both the same while I was using a different namespace in the code files. After discovering what the Default Namespace was really about, I decided to change it to the namespace I was using in code files, and it broke. Ultimately, I did find that you do, in fact, have to reference the resource by default namespace, not assembly name.

I think that one kind of "exception" is generated for the missing resource but only in client side is "visible".

Generally I make two different error:- Everything ok, but I forget to set the embedded resource to true for the resource: we'll get an "empty" content for the script tag then.- Wrong resource name (miss typed): you get "exception" content on the client side in your script tag.

Both are hard to detect because when you check in the browser the page's source you see only the script tag but not it's content. To see the content of the script tags (and detect the nothing/the exception) you need some decent developer add-in for your browser (I'm using firefox with firebug add-in.)

Hi does anyone know how to embed an aspx page - and what content type to use. I embedded an aspx and set the content type to "text/html" but it rendered only the html component of the page, and did not do any of the scripting...thanks

Why would i want to? I was wanting to embed a page that acted as a print preview on a dynamically generated image (i.e. at any point you never know what the image is called). So what I would do is open up this new page, regenerate the image and load it up (only bigger and formatted for printing) and then reference it using server.mapPath(Request.applicationPath &.........). I have worked around this by generating a temporary html file which displays all the data after the server calls. I was not wanting to go that route since I would then need to write code to delete the temporary files older than x hours, thereby affecting page load or page unload performance, but alas i had to. If I had an embedded server page, I would simply need one page with a Session reference to the image (or something like that). I still believe it must be possible as the freetextbox (http://freetextbox.com/) control has an embeeded page with a image picker whic allows you to upload images etc etc.. But no worries and thanks for the response

you tell how to write out the url for another embedded resource inside an embedded resource but what if i want to simply write out some text or a variabel inside a embedded resource ?

My problem is that i have created a custom control for a radio button where it is possible to show a picture instead of the radio button. It have 2 states which is unchecked and checked state.Soo what i do is that i simply write the url to the pictures when creating the control, and then i need the urls to be written out in my embedded css (stylesheet) file, but i cant find out how to do it.