Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

The Asp.NET 2.0 allows to provide JS files in embedded resources using WebResource.axd.

The procedure is well described here and here. Note that adding [assembly: WebResourceAttribute] attibute is important.

However  the methods ClientScript.RegisterClientScriptResource and ClientScript.GetWebResourceUrl do not throw exceptions, if embedded resource  is missing. They just generate invalid urls that can't be visually checked because parameters are encrypted.
For easier identification of the error it is a good practice to check existence of resource prior to call using Debug.Assert or throw exception.

Type rstype = typeof(ClassInAssemblyWithResource);
Debug
.Assert(null != rstype.Assembly.GetManifestResourceInfo(sFullName));
return page.ClientScript.GetWebResourceUrl(rstype, sFullName);

OR better way
StreamHelper.EnsureWebResourceValid(sFullName, rsType.Assembly,true)
page.ClientScript.RegisterClientScriptResource(rsType, FileName)

where EnsureWebResourceValid is the following function

        public static bool EnsureWebResourceValid(string ResName, Assembly Asm,bool ThrowException)

        {

            bool bRet = StreamHelper.EnsureManifestResourceExist(ResName, Asm, ThrowException);

            if(bRet==true)

            { //find the attribute

                bRet = false;

                // Iterate through the attributes for the assembly.

                foreach (Attribute attr in Attribute.GetCustomAttributes(Asm))

                {

                    //Check for WebResource attributes.

                    if (attr.GetType() == typeof(WebResourceAttribute))

                    {

                        WebResourceAttribute wra = (WebResourceAttribute)attr;

                        Debug.WriteLine ("Resource in the assembly: " + wra.WebResource.ToString() +

                          " with ContentType = " + wra.ContentType.ToString() +

                          " and PerformsSubstitution = " + wra.PerformSubstitution.ToString() );

                        if (wra.WebResource== ResName)

                        {

                            bRet = true;

                            break;

                        }

                    }

                }//foreach

            } //ManifestResourceExist

            if(bRet==false)

            {

                string sMsg="Embedded resource " + ResName + " in assembly " + Asm.FullName + " doesn't have WebResourceAttribute ";

                if (ThrowException == true)

                {

                   throw new ApplicationException(sMsg);

                }

                else

                {

                    Debug.Assert(false, sMsg);

                }

            }

            return bRet;

        }

        //'if ThrowException=true, then Throw exception if resource not found

        public static bool EnsureManifestResourceExist(string ResName, Assembly Asm, bool ThrowException)

        {   //NOTE: If resource is located in subfolder of C# project, path of subfolder should be specified (it is included as part of namespace)

            //' Resources are named using a fully qualified name ((including namespace).

            bool bRet=true;  

            ManifestResourceInfo info = Asm.GetManifestResourceInfo(ResName);

            if (info == null)

            {

                bRet=false;

                string sMsg = "Couldn't find embedded resource " + ResName + " in assembly " + Asm.FullName;

                if (ThrowException)

                {

                    throw new ApplicationException(sMsg);

                }

                else

                {

                    Debug.Assert(false, sMsg);

                }

            }

            return bRet;

        }

 

 

 

 I've submitted a suggestion to MS.

 

posted @ Friday, May 26, 2006 10:21 AM

Print

Comments on this entry:

# re: Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

Left by Sloan at 2/28/2007 9:08 AM
Gravatar
Well played Michael.

This has shaved alot of time of my development effort, being able to validate every .js / gif , etc up front. Thanks for the post!

MS, if you're listening, ADD IT IN PLEASE.

# re: Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

Left by Michael Freidgeim at 2/28/2007 9:56 PM
Gravatar

# re: Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

Left by Terry at 4/15/2007 10:56 PM
Gravatar
Great tip. One more for you...any ideas on how to override the <% =WebResource("ResourceName") %> functionality when using PerformSubstitution=true (i.e. in a js/css file). I've wrapped your code in a helper so that I just call WebResourceHelper.RegisterClientScriptResource( page, type, resourceName ) and it first checks to see if the resource is valid then just registers it (just to save me from writing the same two lines of code over and over (I'm lazy)).

So that code works great but right now I have no method of validating resources that are generated during PerformSubstitution=true.

# re: Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

Left by Michael Freidgeim at 4/18/2007 11:31 PM
Gravatar
Terry,
Sorry but I haven't work with PerformSubstitution=true

# re: Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

Left by Nestor at 5/9/2007 1:54 AM
Gravatar
Hi Michael,

You did a great job on this.

I am currently using it to be sure that resources are server as expected.

The only addition that I did inside the &quot;EnsureWebResourceValid&quot; function was to a parameter to the call &quot;Attribute.GetCustomAttributes&quot; for the assemby and the custom attribute type.

changed &quot;Attribute.GetCustomAttributes(Asm)&quot;
to &quot;Attribute.GetCustomAttributes(Asm, typeof(WebResourceAttribute))&quot;

Doing this you only get a collection of attributes for that type instead of getting all of them and checking the attribute type inside the iteration.

I must to say thanks to your perfect solution.

Regards

# re: Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

Left by FOR at 5/19/2007 2:35 AM
Gravatar
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

# re: Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

Left by andrew at 4/7/2008 6:31 AM
Gravatar
I was banging my head against the wall about all of this as well. In my case I wanted to use the web resources in a control that was defined inside a web project (instead of as a stand-alone control). The issue was the type I was using when calling GetWebResourceUrl. That method requires a type; you should check your type to ensure the embedded resources are there. Add a PreRender method to the control and check to see if this.GetType().Assembly.GetManifestResourceNames() actually returns a list of assemblies. In my case it didn't because the control was put into a seperate .dll (even though it's part of the web project!) than the "main" website. In my case I have a Header control that I declare and use in my website, when doing "this.GetType()" in the Header control's codebehind I noticed that the temporary .dll generated by .net was different than the main .dll. To get the correct type I declared an instance of my homepage (called Home.aspx) and got its type instead:

Project1.Home h = new Home();

Now, when I do h.GetType().Assembly.GetManifestResourceNames() I see the correct list of resources. I then pass h.GetType() to the GetWebResourceUrl method and all works as expected.

# re: Check that embedded resource exist before calling ClientScript.RegisterClientScriptResource or GetWebResourceUrl

Left by CodeSlappy at 9/2/2008 11:34 PM
Gravatar
Thanks for the article. I now have my GetWebResourceUrl code working. Also thanks to comment left by andrew, which was also a big help.

Your comment:



 (will not be displayed)


 
 
 
Please add 2 and 4 and type the answer here:
 

Live Comment Preview:

 
«October»
SunMonTueWedThuFriSat
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678