Tuesday, October 8, 2013

WebResource.axd The resource cannot be found 404

Web Resources are a very nice features of .net giving the developer the capability to bundle a bunch of files into a single DLL for easy transport.  However, it is not very forgiving when it comes to coding errors.  There are a lot of sites out there that offer details on how to add a web reference, what is missed is just how precise each piece must be written.  Unfortunately when it breaks the errors are simple 404's which are not helpful in the least.

Step 1: Include the file in your project, right click, to go properties, and set it as an Embedded Resource.

Step 2: add: [assembly: WebResource("DefaultNamespace.Folder1.Folder2.FileName.png", "image/png")]

This step has a couple of gotcha's.  First the contentType (the second parameter) must be correct, WebResource.axd will serve up the file with this content type.  So a content type of text/html used with an image file will result in a screen full of ascii.

Secondly the first parameter is the name of the file after it has been compiled.  A reflector tool comes in very handy here for verification purposes, I use dotPeek.  When compiled the file is named using the folder structure it is contained in prefixed by the Default namespace with periods as separators.  The Default namespace can be found by right clicking on the project name and opening properties.  Note: it is NOT the assembly name.  Failure to perform this part correctly will simply result in the file never being found, again a 404 error.

Step 3: Use something like this:

this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "DefaultNamespace.Folder1.Folder2.FileName.png");

this.Page.ClientScript.RegisterClientScriptResource(this.GetType(), "DefaultNamespace.Folder1.Folder2.FileName.js");

Those lines allow you to get the URL for an image, or add a script reference at the beginning of the HTML output for the page.  Notice how the filename referenced is IDENTICAL to the filename used in the [assembly: tag up above?  If these two do not match and are not correct then it will result in a 404 error; although a URL or script reference may still be generated, it will not be the correct one.

Also, the GetType() call is very important as well.  The type referenced must at the least be in the same project as the embedded resource, one person said it needed to be in the same folder as well, but I am fairly certain that is not the case.  To play it safe I just use this.GetType() in the local file or Resource.cs file that generates the WebResource URL.  I say playing it safe because I have been bitten before by renaming my Resource.cs file and having my typeof(PageName) reference a completely different, but still valid object.  This resulted in no compile errors and a good looking URL, but always 404 errors.

Troubleshooting:

It can be very helpful to determine which /WebResource.axd is the one you are looking for in your HTML source code.  To help with this someone over at Telerik has created a nice page that allows you to decrypt the URL and see a more friendly name.

Something to look for in the friendly name is your assembly name, if it does not reference the assembly that houses the embedded resource then you probably screwed up the Type when generating the URL.

Tuesday, October 1, 2013

Upgrading from Microsoft.Practices.EnterpriseLibrary v 3.0 to v 6.0

Obviously the versions I was jumping in between are quite different, this application had not been upgraded in some time.  Taking one step at a time I decided to start by swapping out the DLLs.  I ran into a minor issue when I only modified the references for one of the projects in my solution to the new version, somehow one of the other projects rolled back the files during compile time to the previous version.  Re-updating the files and modifying the references for all the projects at once solved that issue.

But then I was presented with an odd error:

The type or namespace name 'Practices' does not exist in the namespace 'Microsoft'

It was especially confusing since intellisense and object name highlighting was detecting the presence of the namespace correctly.  After some web searching I ran into this thread, which implied that the target version of the framework I was building for needed to be newer or different then the one I was currently using.  I had yet to convert the project over so I was still compiling for version 3.5 of the framework.  I changed that to version 4.5 and was then able to build successfully.

------------

Unfortunately that was not the end of my problems.  I was using asp:ScriptManager in my project ( any control that references ScriptManager, such as the replacement control from the AjaxControlToolkit, will also have this issue ) and as a result when I tried running the project under the .net 4.0 web engine I got this error:

Could not load type 'System.Runtime.CompilerServices.ExtensionAttribute'....

I was unable to find a work around for that error as long as I was using the ScriptManager control.  If I removed that control then the web application worked perfectly.  Since my server only had windows 2003 on it upgrading IIS to .net 4.5 was not an option.  I finally decided to roll back from EnterpriseLibrary v6.0 to v5.0.414 and build the project for .net 4.0 instead of 4.5.

This worked well until I started getting an odd error:

Could not load file or assembly 'Microsoft.Practices.EnterpriseLibrary.Data, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.

It turned out that one of my solutions was hanging onto an old version of one of my other projects DLLs, even though the primary project was referencing the sub project in my solution apparently it did not refresh that sub projects DLL in its cache.  This was an issue since at one point I had the sub project referencing version 6.0.0.0 of the EnterpriseLibrary DLL.  I removed and re-added the primary project's reference to the sub project, the cache refreshed itself and all was well.