Tales of development

Utilising MEF to self-register HTTP modules

After reading about .NET 4’s new PreApplicationStart method being used to register build providers without touching the web.config. I thought about other instances where editing the web.config was mundane. The first thing that came to mind was registering HTTP modules.

HTTP Modules are a fantastic way to intercept HTTP requests, and “inject” code at each stage of the request lifecycle, and they are invaluable for sectioning code into pluggable components for reuse in another application. The only thing that’s bugged me is the need to register each module by adding an entry in the <httpModules> section within the web.config.

Clearly great minds think alike. David Ebbo, an architect on the ASP.NET team announced a RegisterModule() API had been added in MVC3 allowing HttpModules to be registered without touching config, by using code like below:

    [assembly: System.Web.PreApplicationStartMethod(typeof(Initializer), "Initialize")]
    public static class Initializer
        public static void Initialize()

Yes it has it’s advantages, but this feels more like a step sideways than a step forward. Each module still has to be explicitly defined, so it’s almost exactly the same steps as adding a HttpModule via the web.config, albeit a slightly different syntax.

This got me wondering if there was an easy way to discover modules and automatically register them using the RegisterModule method, and that seemed like a perfect scenario for MEF.

Managed Extensibility Framework (MEF)

MEF is a component of .NET 4.0 for creating lightweight, extensible applications. Extensions (known as parts, or exports) can be dynamically discovered (imported) from a configurable location (known as a Catalog) and used at run-time with no configuration required.

MEF uses an attributed programming model where “imports” and “exports” are declared by decorating classes or members with the Import and Export attributes.

An Import is matched with one or more Exports, providing they have the same “contract”. The contract consists of a string, called the contract name, and the type of the exported or imported object, called the contract type. Only if both the contract name and contract type match is an export considered to be a match.


Usually classes are marked with the ExportAttribute but I wanted something that’s more distinct and self-explanatory. Therefore I created a new attribute, derived from the standard ExportAttribute. The code for the attribute is as follows:

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class AutoRegisterHttpModuleAttribute : ExportAttribute, IMefMetaData
        public AutoRegisterHttpModuleAttribute() : base(typeof(IHttpModule))
            Enabled = true;

        public bool Enabled
            get; set;

        public string Name
            get; set;

Nothing unusual here, except the MetadataAttribute. This informs MEF that there is additional metadata to be exposed. There isn’t necessarily a requirement for any metadata, but I’ve taken the opportunity to add some basic properties to assist us (I’ll describe this later).

The metadata is abstracted to an interface named IMefMetaData , known as a metadata view. A metadata view must have only properties, and those properties must only have get accessors.

    public interface IMefMetaData
        bool Enabled

        string Name

Back to the attribute, note the Type parameter passed into the base constructor, this just defines the Type of our contract stating it must be of type IHttpModule.

Now we have an attribute with which to decorate our HttpModules, we need to instruct MEF to discover and import any classes marked with this attribute and compose them into a Catalog.

Discovery and Import

As mentioned above, a MEF contract is just a string (when importing by type, it’s just the name of that type). There are two ways you can define an Import in MEF, Import and ImportMany with cardinality being the difference.

The Import attribute refers only to single imports. (zero-to-one and exactly-one cardinalities). Marking a property with this attribute specifies there is a single instance of the stated contract, and there is a single source to match.

Using ImportMany attribute declares zero-to-many cardinality, and states that instead of a single export, there can be many exports which match the contract. Using it on an IEnumerable, as shown below, MEF will fill the IEnumerable with all parts it can find that export that type, in this case IHttpModule.

        public IEnumerable<IHttpModule> Modules { get; set; }

Usually this is sufficient, but because we want to use some metadata, we need to alter the property signature in order to expose it. MEF provides an overload of Lazy<T> to allow access to the metadata without instantiating the underlying export. The corresponding property signature looks like this:

        public IEnumerable<Lazy<IHttpModule, IMefMetaData>> Modules
            get; set;

The property alone won’t do a thing, we need to instruct MEF to discover parts and populate this property. Firstly we tell MEF we want to discover attributed parts within the application’s bin directory by using the DirectoryCatalogclass. Next we create a CompositionContainer to hold the parts for composition and finally we tell MEF to Compose the Import parts within this class:

        var catalog = new DirectoryCatalog(HttpRuntime.BinDirectory);
        var container = new CompositionContainer(catalog);

This populates the Modules property with all classes decorated with the attribute we defined earlier, so we should now have an IEnumerable list of HttpModules that need to be auto-registered, so we now just need to call the RegisterModule method for each module:

        foreach (var httpModule in this.Modules.Where(m => m.Metadata.Enabled))
            var msg = httpModule.Metadata.Name ?? httpModule.GetType().FullName;

            log.InfoFormat("Adding SelfRegistering HttpModule {0}", msg);

So by utilising the metadata added earlier, we can add some rudimentary notifications using log4net, showing which modules are being registered (helpful for debugging) and we also have a facility to easily disable modules in code to also assist in debugging etc.


So now instead of registering a HttpModule via the web.config, we simply decorate it with the AutoRegisterHttpModuleAttribute. It will get automatically registered and will intercept any requests as normal.

In my opinion this “shortcut” is an absolute godsend for distributing self-contained projects and sharing code between solutions with minimal configuration - HttpModules can now really be the “plug-ins” I think they were intended to be.


I foresee only one issue whereby it could take other developers a while to find and debug any issues if they are being caused by a self-registered HttpModule. However once we become accustomed to using this method of registering modules, it should be easy enough to find modules using the “Find usages” feature within Visual Studio. A minor issue compared to the benefits this offers.

Future ideas and Code download

I will shortly be uploading the full VS solution (probably to EPiCode), but first I want to add a few useful additions in there that utilise this technique, and I’ll write some more blog posts explaining those awesome plugins.

Watch this space. Smile

Comments (9) -

  • Paul

    1/17/2012 7:28:44 PM | Reply

    I'm not sure if I'm reading the code right, but should the line:
        var msg = httpModule.Metadata.Name ?? httpModule.GetType().FullName;
    actually be
        var msg = httpModule.Metadata.Name ?? httpModule.Value.GetType().FullName;

    • tompipe

      1/17/2012 8:36:01 PM | Reply

      Good spot Paul. It should indeed.


  • Chris Marisic

    1/18/2012 3:17:29 PM | Reply

    I think this pattern is somewhat overkill.

    It would be much easier to just ship your http module along with a App_Start WebActivator configuration that registers itself against the DynamicModuleUtility

    [assembly: PreApplicationStartMethod(typeof(MySessionModuleRegistration), "Start")]
    public static class MySessionModuleRegistration
        public static void Start()
            var moduleType = MyEnviroment.Mode == ModeTypes.Debug
                                    ? typeof(DebugModule)
                                    : typeof(MySessionModule);


    Even makes it trivial to swap out entire modules for debug usage.

    • tompipe

      1/18/2012 3:21:26 PM | Reply

      This wont work if you have multiple modules contained in one dll.

      Each library can only have one PreApplicationStartMethod

      • Betty

        1/19/2012 6:02:05 AM | Reply

        Not if you use WebActivator ( &

        • tompipe

          1/20/2012 9:53:08 AM | Reply

          That WebActivator does look interesting. I'll bear that in mind in future.

          Personally I much prefer to just decorate a module with an attribute rather than digging through the project (or another one) to find the activation code (if I'm having a hard time remembering it)

          Also for maintainability reasons I would prefer the activation code to be in a single location, and not littered about in every module.

  • Asame Obiomah

    2/12/2012 12:21:40 AM | Reply

    I don't get the point of going down the MEF route. For PreApplicationStart to run, the application needs to be restarted which defeats the purpose of discoverability; the application restarted.
    Also, if the benefit is to avoid compiling, the global.asax can read module names from a config or text file, database etc, then instantiate the modules and load them with very little variation to David Ebbo's code and without touching the web.config.

  • High Speed Internet Blogger

    4/9/2012 5:14:13 AM | Reply

    I agree with Asame, the point of going down the MEF route is really questionable. Such stuffs must be done first before runnung the PreApplicationStart.

  • Mike James

    4/22/2012 2:23:00 AM | Reply

    Tom, I agree its a pain for the activation code to be all over the place.

    Can you let me know the full VS solution is available and if you post anything new on the subject.

Pingbacks and trackbacks (3)+