Help! My Web Application Throws an Insane Amount of TypeLoadExceptions!

One of the first things I noticed when I started debugging our web application was that at load I got an insane amount of these:

A first chance exception of type 'System.TypeLoadException' occurred in System.Web.dll
A first chance exception of type 'System.TypeLoadException' occurred in System.Web.dll
A first chance exception of type 'System.TypeLoadException' occurred in System.Web.dll
...

After digging into the code, I found out that during the loading process of controls, ASP.NET tries to find the type that matches a certain tag. The following code piece from System.Web.UI.NamespaceTagNameToTypeMapper (line 82):

Type type = null; 

// If loading the type from the assembly depends on a referenced assembly that cannot
// be loaded, we should throw the actual exception, instead of later reporting a more
// generic error saying the type was not found (Devdiv 138674) 
try {
    type = _assembly.GetType(typeName, true /*throwOnError*/, true /*ignoreCase*/); 
} 
catch (System.IO.FileNotFoundException) {
    throw; 
}
catch (System.IO.FileLoadException) {
    throw;
} 
catch (BadImageFormatException) {
    throw; 
} 
catch {
    // For all other exceptions, such as when the type is not present in the assembly, 
    // we ignore the exception so that we can continue to check other assemblies to look
    // for the type.
}
return type;

What the hell?! This is a horrible bottleneck!

What's the solution, you ask? Well, it's simple - just tell ASP.NET ahead of time where your controls are with the @ Register directive. For instance:

<%@ Register Assembly="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" 
             Namespace="System.Web.UI.WebControls" TagPrefix="wc" %>

This gives ASP.NET a little hint, telling it that if it wants controls with the wc tag prefix, it should look for them in the System.Web.UI.WebControls namespace in the System.Web assembly. Then all you have to do is to mark all of the controls that come from that namespace in that assembly with that specific prefix, as such:

<wc:Literal ID="Something" runat="server"></wc:Literal>

And that's that. No more annoying exceptions.

Make sure to use the full assembly name in the @ Register directive, otherwise you'll get a System.IO.FileNotFoundException thrown when ASP.NET can't find the assembly.

One more thing that's important to note is that if you have only a few of these, set your web.config's compilation element's batch attribute to false, which means ASP.NET will load pages on demand. This way you'll know the culprit page when you hit it for the first time, rather than have the exception thrown when the whole application starts.

[Update: An application-wide solution would be to use the system.web / pages / controls element in the web.config to declare prefixes for all of your controls, rather than at the single page level:

<configuration>
  <system.web>
    <pages>
      <controls>
        <add tagPrefix="wc" namespace="System.Web.UI.WebControls"
assembly="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>

And thanks to Ofer Bar from my team for the tip.]

10 Comments

  • Hi Omar,

    Interesting find.

    Are you saying that:


    Would replace the normal syntax?


    What are the implications performance-wise? Quicker start up due to less exceptions having to be handled?

  • Hey Dave,

    First of all, the name's Omer, not Omar :)

    What you're doing by using the custom prefix is taking away ASP.NET's need to find the control by itself in all loaded assemblies by explicitly telling it where the control is. That would drastically increase load time, because you'd have saved the time it takes to throw exceptions for each control you use in your application and for each assembly that control may be in.

  • Hello,

    I have this same problem and I tried to fix it has you say, but it continues to give me a lots of same error.
    On my web.config is






    I'm using Ajax and I'm using a Iframe to capture diferente pages im my WebApplication. I don't know what more I can do. Can you help me?

    Thanks very much

  • You should not use 'asp', since it's a reserved prefix with two possibilities, so it might throw these exceptions. Use some other prefix instead and make sure that no control's tag in your application uses 'asp' as a prefix.

  • Thank you very much!

    I used another tagprefix as you say and it resolved this problem. Thanks once more!

  • Thanks for the great information. Do you know if there's been a bug report filed about this? Do you think this problem would noticeably impact performance?

    This workaround around hides the "asp" prefix from intellisense, but any controls that are dragged from the toolbox still sport the "asp" prefix.

  • It's not a bug, but rather 'by-design' and I gave up on trying to file 'by-design' bugs a long time ago. They just don't get fixed.
    Performance will only be impacted if you use batch="false" and even then only once per page, since this happens when ASP.NET compiles the pages. Not a big hit, but very annoying when starting to debug a project with a LOT of aspx files.

  • Thanks, Omer. I just started a new application with VS 2008 that has pretty stringent performance requirements and was worried this would affect it. You've been a big help.

  • You know I'm pretty sure this is a bottleneck for the application anytime it starts, not just during a debug session. Because some of my web applications are not used all that often, so IIS shuts them down after awhile. So the user experience is that the first time you try to load the web page, it just sits there for about 5-10 seconds trying to start up. It is really embarrassing to me, and I have not been able to speed this up. I will give your method a try.

    Thank you.

  • thanks,omer.i have same question
    i found out that


    in the web.config
    so,i change it to System.Web.UI.WebControls

Comments have been disabled for this content.