Wednesday, October 24, 2007

Debugging VS.NET Design time

Just came across an excellent article on Brennan's Blog explaining in detail how to setup Visual Studio to enable debugging of design time code. In short here's what it boils down to:
  1. In Visual Studio set the debug properties on the (Class Library) project you want to debug to 'Launch an external program' and make that program Visual Studio. In most cases that would be : C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe
  2. Save the properties and setup your breakpoints. Now right click the project and from the popup menu choose Debug > Start new instance.
  3. A new instance of Visual Studio fires op. Now, in the new instance, load a simple project that uses the project you want to debug and you're good to go.
This even helps debug build issues in things like VirtualPathProviders and ResourceProviders. Read the full article

Monday, October 1, 2007

The mysterious problem with WebResource.axd

Ever since I've started using embedded resources I've been running into this problem:

The WebResource.axd handler must be registered in the
configuration to process this request.
It occurs when an application is updated with an assembly that uses embedded resources.

It's a rather nasty problem because it will persist until the worker process is fully restarted. This is because the exception is triggered by a static field that is evaluated only once (!). Fredrik Haglund describes the mechanism here. Fredrik also offers a workaround, but it's a dirty one using reflection to tweak private variables. This work around will probably only work in full trust sites and may break with future updates of .NET. It does however get the job done for now.

Here's the code (slightly modified from Fredrik's version):
public static void WebResourceHandlerFix()
{
Type type = typeof( System.Web.Handlers.AssemblyResourceLoader );

System.Reflection.FieldInfo handlerExistsField =
type.GetField( "_handlerExists",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static );

System.Reflection.FieldInfo handlerExistsCheckedField =
type.GetField( "_handlerExistenceChecked",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static );

if ( null != handlerExistsCheckedField &&
null != handlerExistsField )
{
if ( ( bool )handlerExistsCheckedField.GetValue( null ) &&
    !( bool )handlerExistsField.GetValue( null ) )
   handlerExistsCheckedField.SetValue( null, false );
}
}
}

Note: This problem can also occur when trying to map URL's to a handler through a section in web.config. For example, this may cause problems:

<location path="virtualpage.aspx">
<system.web>
 <httphandlers>
    <add path="*" verb="*" type="Example.Web.Customhandler" />
 </httphandlers>
</system.web>
</location>

Because it will override the handler for WebResource.axd. Instead, try to add the mapping for the virtual page to the main <httphandlers> section in web.config.