Three Hidden Extensibility Gems in ASP.NET 4

asp.net, code 0 comments suggest edit

ASP.NET 4 introduces a few new extensibility APIs that live the hermit lifestyle away from the public eye. They’re not exactly hidden - they are well documented on MSDN - but they aren’t well publicized. It’s about time we shine a spotlight on them.

PreApplicationStartMethodAttribute

This new attribute allows you to have code run way early in the ASP.NET pipeline as an application starts up. I mean way early, even before Application_Start.

This happens to also be before code in your App_code folder (assuming you have any code in there) has been compiled.

To use this attribute, create a class library and add this attribute as an assembly level attribute. A common place to add this would be in the AssemblyInfo.cs class within the Properties folder.

Here’s an example:

[assembly: PreApplicationStartMethod(
  typeof(SomeClassLib.Initializer), "Initialize")]

Note that I specified a type and a method. That method needs to be a public static void method with no arguments. Now, any ASP.NET website that references this assembly will call the Initialize method when the application is about to start, giving this method a chance to do perform some early initialization.

public static class Initializer
{
  public static void Initialize() { 
    // Whatever can we do here?
  }
}

The primary use of this feature is to enable tasks that can’t be done within Application_Start because it’s too late. For example, registering build providers and adding assembly references.

Which leads us to…

BuildProvider.RegisterBuildProvider

As you might guess, if one of the key scenarios for the previously mentioned feature is to allow registering build providers, well ASP.NET better darn well allow you to register them programmatically.

Prior to ASP.NET 4, the only way to register a custom build provider was via the <buildproviders> node within web.config. But now, you can register them programmatically via a call to the new BuildProvider.RegisterBuildProvider method.

BuildProvider.RegisterBuildProvider(".foo", typeof(MyBuildProvider));

Combining the PreApplicationStartMethodAttribute with this method call means that installing a build provider can be done in one step -simply reference the assembly with the build provider and the assembly can register it for you. Whereas before, you would have to reference the assembly and then muck around with web.config.

I think I speak for us all when I say “Yay! Less junk in my web.config trunk!”

BuildManager.AddReferencedAssembly

Another new method added in ASP.NET 4 allows adding an assembly to the application’s list of referenced assemblies. This is equivalent to adding an assembly to the <assemblies> section of web.config.

As you might guess, this comes in handy when registering a custom build provider. It allows you to programmatically add references to assemblies that may be needed by your build provider.

Oh, and it’s yet another way to reduce the size of your web.config file. Who doesn’t love that? :)

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

19 responses

  1. Avatar for Chris Cavanagh
    Chris Cavanagh May 16th, 2010

    Phil - Any issues with implementing the PreApplicationStartMethod directly in the web app that uses it? (rather than a separate assembly). I'm already doing this successfully, but could separate it if necessary (weird side effects etc). Thanks!

  2. Avatar for Chris Cavanagh
    Chris Cavanagh May 16th, 2010

    To clarify... Meant to say "if there were weird side effects". Currently seems to be behaving itself :) (note if debugging through IIS rather than Cassini it can look like the method isn't getting called (breakpoints don't get hit), but it does actually work fine).

  3. Avatar for Sergio Pereira
    Sergio Pereira May 16th, 2010

    Does VS also run these initializers? I mean, if I add an assembly reference like that, will VS recognize its types in an .aspx file for example? In the past I had problems when I did similar things (like adding a virtual path provider) and confusing VS' designers.

  4. Avatar for Bret Ferrier
    Bret Ferrier May 16th, 2010

    Just one question. Are there any examples off the top of your head that you can think of where people are using these new .Net 4.0 features?

  5. Avatar for Ren&#233; Kuss
    Ren&#233; Kuss May 16th, 2010

    I'm using the PreApplicationStartMethodAttribute to configure a di container. It works without any problems. No more bogus configuration code in global.asax.

  6. Avatar for haacked
    haacked May 17th, 2010

    @Chris there's nothing special about a web app as far as ASP.NET is concerned at runtime. It gets compiled as just another assembly. So I can't imagine there'd be any weird side effects.
    @Bret One obvious one would be to register a custom build provider. For example, Subsonic used to ship with a build provider. With this approach, manual configuration in web.config would've been unnecessary.
    You'll see more examples coming from our team in the future.

  7. Avatar for Thanigainathan
    Thanigainathan May 17th, 2010

    Hi,
    BuildManager.AddReferencedAssembly will register a assembly at runtime. So I cannot really access the classes inside them during the design time right ?
    Please explain this.
    Thanks,
    Thanigainathan.S

  8. Avatar for haacked
    haacked May 18th, 2010

    @Thanigainathan that's right. If you want it at design time, just add a project reference.

  9. Avatar for Ben
    Ben May 18th, 2010

    Would it be possible to use that RegisterBuildProvider method to minify all of your .js files? Just curious...

  10. Avatar for Joop
    Joop May 20th, 2010

    Strange thing happening to me with the PreApplicationStartMethod Attribute. I did implement it in my latest project. In the AssemblyInfo.cs
    [code]
    [assembly: PreApplicationStartMethod(typeof(MyAssembly.Initializer), "Initialize")]
    namespace MyAssembly
    {
    public static class Initializer
    {
    public static void Initialize()
    {
    TranslationKeys.Initialize();
    }
    }
    }
    [/code]
    When I rebuild my application and load it in the browser I get the following error:
    [blockquote]
    The method specified by the PreApplicationStartMethodAttribute on assembly 'MyWebApp, Version=0.0.1.0, Culture=neutral, PublicKeyToken=null' cannot be resolved. Type: 'MyAssembly.Initializer', MethodName: 'Initialize'. Verify that the type is public and the method is public and static (Shared in Visual Basic).[/blockquote]

  11. Avatar for PeanutButterLou
    PeanutButterLou June 16th, 2010

    YESSSSSSSSS!!!!! Oh man was doing all this auto-install stuff with the assembly level attributes and what-not a pain to get working before this attribute came to be. vnice.

  12. Avatar for Vi
    Vi August 21st, 2010

    Can the combination of these three gems be used to enable custom build providers for Web Application projects?
    Vi

  13. Avatar for Interactive Intelligence
    Interactive Intelligence January 31st, 2011

    Never knew these extensibility APIs existed- why is it you think these aren’t better publicized? I love the fact that you can register a custom build provider programmatically with this API, plus the efficiency of installing the build provider in one step! I see smaller web.config files in the future with this gem...everyone has to love that!

  14. Avatar for Per Samuelsson
    Per Samuelsson August 9th, 2011

    @Phil,
    Thanks for sharing your insight.
    @all,
    FWIW, I was hoping this could be a big help for a problem we have, relating to assembly reference resolving in ASP.NET, but unfortunally, we were not able to use it since (as it seems) the initializer you register using the PreApplicationStartMethodAttribute is never fired if applied on an assembly residing in the GAC. Which is the case in our design.
    Just thought I'd share this.

  15. Avatar for Frode
    Frode February 23rd, 2012

    I've been using the AppInitialize technique lately and wanted to try out the PreApplicationStartMethod attribute.
    My initialization code reads a custom config section and this failed with a ConfigurationErrorsException using PreApplicationStartMethod.
    "An error occurred creating the configuration section handler for testproject: This method cannot be called during the application's pre-start initialization stage. ".
    Is there another attribute that can trigger my initalization code at a later moment? Like AppInitialize?

  16. Avatar for Saeed Neamati
    Saeed Neamati June 5th, 2012

    Hell yeah, I love you Haacked. I was developing a plugin architecture for ASP.NET MVC, and I had no idea how to move my plugin DLL files into bin folder dynamically. This solved it.
    Thanks man.

  17. Avatar for Hannah
    Hannah December 24th, 2012

    Yay, I love all this side-effecting code. Who cares is side-effecting is universally recognized as a nasty, global, non-OO practice? I mean, it is really cool when you look at code and have absolutely no idea how it will behave at runtime because magic attributes in obscure code locations are injecting behaviors everywhere.
    One thing is for sure though - by the time you figure any of this out, another dot release from Microsoft will completely change the infrastructure yet again. Talk about fracturing your developer community.

  18. Avatar for joey
    joey January 15th, 2013

    It allows you to programmatically add references to assemblies that may be needed by your build provider.
    L7805CV

  19. Avatar for Graiden Elliott
    Graiden Elliott April 25th, 2013

    App_Code contains all standalone .cs or .vb files and they are compiled
    automatically whenever you change anything in the files within.