Dependency Injection With ASP.NET HttpModules

At the risk of getting punched in the face by my friend Miguel, I’m not afraid to admit I’m a fan of responsible use of dependency injection. However, for many folks, attempting to use DI runs into a roadblock when it comes to ASP.NET HttpModule.

In the past, I typically used “Poor man’s DI” for this. I wasn’t raised in an affluent family, so I guess I don’t have as much of a problem with this approach that others do.

However, when the opportunity for something better comes along, I’ll take it Daddy Warbucks. I was refactoring some code in Subtext when it occurred to me that the new ability to register HttpModules dynamically using the PreApplicationStartMethodAttribute could come in very handy.

Unfortunately, the API only allows for registering a module by type, which means the module requires a default constructor. However, as with many problems in computer science, the solution is another layer of redirection.

In this case, I wrote a container HttpModule that itself calls into the  the DependencyResolver feature of ASP.NET MVC 3 in order to find and initialize the http modules registered via your IoC/DI container. The approach I took happens to be very much similar to one that Mauricio Scheffer blogged about a while ago.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using HttpModuleMagic;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;

[assembly: PreApplicationStartMethod(typeof(ContainerHttpModule), "Start")]
namespace HttpModuleMagic
{
  public class ContainerHttpModule : IHttpModule
  {
    public static void Start()
    {
      DynamicModuleUtility.RegisterModule(typeof(ContainerHttpModule));
    }

    Lazy<IEnumerable<IHttpModule>> _modules 
      = new Lazy<IEnumerable<IHttpModule>>(RetrieveModules);

    private static IEnumerable<IHttpModule> RetrieveModules()
    {
      return DependencyResolver.Current.GetServices<IHttpModule>();
    }

    public void Dispose()
    {
      var modules = _modules.Value;
      foreach (var module in modules)
      {
        var disposableModule = module as IDisposable;
        if (disposableModule != null)
        {
          disposableModule.Dispose();
        }
      }
    }

    public void Init(HttpApplication context)
    {
      var modules = _modules.Value;
      foreach (var module in modules)
      {
        module.Init(context);
      }
    }
  }
}

The code is pretty straightforward, though there’s a lot going on here. At the top of the class we use the PreApplicationStartMethodAttribute which allows the http module to register itself! Just reference the assembly containing this code and you’re all set to go. No mucking around with web.config!

Note that this code does require that you’re application has the following two assemblies in bin:

  1. System.Web.Mvc.dll 3.0
  2. Microsoft.Web.Infrastructure.dll 1.0

The nice part about this is after referencing this assembly, I can simply register the Http Modules using my favorite DI container and I’m good to go. For example, I installed the Ninject.Mvc3 package and added the following Subtext http module bindings:

kernel.Bind<IHttpModule>().To<BlogRequestModule>();
kernel.Bind<IHttpModule>().To<FormToBasicAuthenticationModule>();
kernel.Bind<IHttpModule>().To<AuthenticationModule>();
kernel.Bind<IHttpModule>().To<InstallationCheckModule>();
kernel.Bind<IHttpModule>().To<CompressionModule>();

There is one caveat I should point out. You’ll notice that when the container http module is disposed, Dispose is called on each of the registered http modules.

This could be problematic if you happen to register them in singleton scope. In my case, all of my modules are stateless and the Dispose method is a no-op, which in general is a good idea unless you absolutely need to hold onto state.

If your modules do hold onto state and need to be disposed of, you’ll have to be careful to scope your http modules appropriately. It’s possible for multiple instances of your http module to be created in an ASP.NET application.

DI for a Single Http Module

Just in case your DI container doesn’t support the ability to register multiple instances of a type (in other words, it doesn’t support the DependencyResolver.GetServices call), or it can’t handle the scoping properly and your http module holds onto state that needs to be disposed at the right time, I did write another class for registering an individual module, while still allowing your DI container to hook into creation of that one module.

In this case, you won’t be using DI to register the set of http modules. But you will be using it to create instances of the modules that you register.

Here’s the class.

using System;
using System.Web;
using System.Web.Mvc;

namespace HttpModuleMagic
{
  public class ContainerHttpModule<TModule> 
    : IHttpModule where TModule : IHttpModule
  {
    Lazy<IHttpModule> _module = new Lazy<IHttpModule>(RetrieveModule);

    private static IHttpModule RetrieveModule()
    {
      return DependencyResolver.Current.GetService<IHttpModule>();
    }

    public void Dispose()
    {
      _module.Value.Dispose();
    }

    public void Init(HttpApplication context)
    {
      _module.Value.Init(context);
    }
  }
}

This module is much like the other container one, but it only wraps a single http module. You would register it like so:

DynamicModuleUtility.RegisterModule(typeof(ContainerHttpModule<MyHttpModule>));

In this case, you’d need to set up your own PreApplicationStartMethod attribute or use the WebActivator.

And of course, I created a little NuGet package for this.

Install-Package HttpModuleMagic

Note that this requires that you install it into an application with the ASP.NET MVC 3 assemblies.

What others have said

Requesting Gravatar... Paul Jun 02, 2011 6:09 PM
# re: Dependency Injection With ASP.NET HttpModules
Spring.NET does it from years now
Requesting Gravatar... AlexIdsa Jun 02, 2011 6:18 PM
# re: Dependency Injection With ASP.NET HttpModules
What is so wrong with dependency injection? Why should you be punched into face? :)
Requesting Gravatar... Darren Cauthon Jun 02, 2011 7:23 PM
# re: Dependency Injection With ASP.NET HttpModules
Have you tried MVC Turbine? It has been doing this since MVC V1, magically behind-the-scenes and for all ioc containers. If you have a HTTP module, it resolves it out of your ioc container of choice without you having to do one additional line of code.

Cases like these are the main reason I use MVC Turbine, and why I wish its features would g we adopted by ASP.Net MVC. Many devs, if not most, need this functionality. When its not provided by the framework, it leaves EVERY dev to write or copy-paste huge chunks of code that do exactly the same thing. Aren't these the types of problems
Requesting Gravatar... Vishal Pawar Jun 02, 2011 8:25 PM
# re: Dependency Injection With ASP.NET HttpModules
nice info buddy
Requesting Gravatar... Justin Jun 02, 2011 8:46 PM
# re: Dependency Injection With ASP.NET HttpModules
Great post Phil. I tend to use "Poor mans DI" most of the time instead of IoC containers. I appreciate you showing how to use it with HttpModules. Thanks.
Requesting Gravatar... Paul Knopf Jun 02, 2011 8:59 PM
# re: Dependency Injection With ASP.NET HttpModules
Why have DI for httmodules though? Testability? Who tests httpmodules?
Requesting Gravatar... lynn Jun 03, 2011 12:42 AM
# re: Dependency Injection With ASP.NET HttpModules
Nifty. Gotta use this?
Requesting Gravatar... haacked Jun 03, 2011 2:03 AM
# re: Dependency Injection With ASP.NET HttpModules
@Paul, @Darren Do both of those approaches work without requiring changes to Web.config nor Global.asax.cs? In other words, does the mechanism for dynamic registration register itself?

I'm unaware how that could have been accomplished before ASP.NET 4 because there was no way to self register an HTTP Module from outside of the application code without changing the application's web.config or doing some trickery within an application's global.asax.
Requesting Gravatar... Javier Lozano Jun 03, 2011 2:23 AM
# re: Dependency Injection With ASP.NET HttpModules
@phil, @paul, @darren -

Prior to ASP.NET 4 this was not possible since PreApplicationStartMethod hook didn't exist in the runtime. The *only* clean way to do it was to provide your hooks into the class that inherited from HttpApplication (the type that Global.asax inherits from).

A while back, I blogged about how you could do this in ASP.NET 2 (with MVC or WebForms) - lozanotek.com/... ... this blog post outlines the same pieces that I wired into MVC Turbine.
Requesting Gravatar... haacked Jun 03, 2011 3:02 AM
# re: Dependency Injection With ASP.NET HttpModules
@Javier I assume than now, MVCTurbine makes use of this hook to be even more modular, right?
Requesting Gravatar... Seth Jun 04, 2011 4:31 AM
# re: Dependency Injection With ASP.NET HttpModules
> "... the solution is another layer of redirection"

had me rolling on the floor :)
Requesting Gravatar... Chris Jun 04, 2011 6:04 AM
# re: Dependency Injection With ASP.NET HttpModules
so where do you register your module, i mean where is this method called? what class?

DynamicModuleUtility.RegisterModule(typeof(ContainerHttpModule<MyHttpModule>));

i'm a newbie by the way. in case this question sounds odd. nice post i must say. very clear and concise
Requesting Gravatar... Javier Lozano Jun 04, 2011 11:16 AM
# re: Dependency Injection With ASP.NET HttpModules
@Phil - Sorry the delay on the response, as you know, I've been a little busy. :)

Unfortunately it doesn't since that was one of the pieces that I left un-touched for the MVC3 migration. However, it doesn't mean it can't use it. I'm actually in the process of making this change in the v3.3 release along with adding support for removing modules from the pipeline.

At times having things to be auto-wired can be somewhat of a pain since they're not 'developed' with IoC principles in mind.

Once these pieces are done, they will be available through #nuget :)
Requesting Gravatar... Konstantin Tarkus Jun 05, 2011 7:02 AM
# re: Dependency Injection With ASP.NET HttpModules
Nice, nice. I love the idea when you can register HttpModule without touching web.config file.
Requesting Gravatar... Chris Marisic Jun 05, 2011 10:53 PM
# re: Dependency Injection With ASP.NET HttpModules
Shouldn't we all use WebActivator and never use PreApplicationStartMethod?

Isn't PreApplicationStartMethod limited to 1 single usage in your entire application?
Requesting Gravatar... haacked Jun 05, 2011 11:06 PM
# re: Dependency Injection With ASP.NET HttpModules
@chris PreApplicationStartMethodAttribute is an assembly level single use attribute. It means it's single use per assembly, not application.

In this, the assembly would be the HttpMagic assembly that's using it, which only needed it once. Your app is in the clear to reference this assembly. :)
Requesting Gravatar... AlexIdsa Jun 06, 2011 3:03 AM
# re: Dependency Injection With ASP.NET HttpModules
Phil, why do you ignore me? :) I'm really interested in the answer to my question about DI. Is there any new trend of hating DI?
Requesting Gravatar... haacked Jun 06, 2011 4:57 AM
# re: Dependency Injection With ASP.NET HttpModules
@Alexldsa I didn't think that question was for me. I like DI. I don't know why folks would hate it. :)
Requesting Gravatar... AlexIdsa Jun 06, 2011 5:06 AM
# re: Dependency Injection With ASP.NET HttpModules
Phil, but what was a reason for the twit which you told about at the top of the post?
Requesting Gravatar... haacked Jun 06, 2011 5:11 AM
# re: Dependency Injection With ASP.NET HttpModules
@Alexldsa I don't recall the tweet. It was something Miguel De Icaza tweeted or retweeted. Ask him.
Requesting Gravatar... Stacey Jun 08, 2011 10:14 PM
# re: Dependency Injection With ASP.NET HttpModules
That does seem like an odd tweet to make.
Requesting Gravatar... Marco Sep 08, 2011 7:19 AM
# re: Dependency Injection With ASP.NET HttpModules
Thanks for this Phil, made my day.

Having worked on some PHP-applications using frameworks like Symfony, I'm fairly new to ASP.NET and this is exactly what I needed (I need to investigate and learn a lot more). Thanks again!

About that tweet you mentioned, I don't agree... DI and unit testing = great!
Requesting Gravatar... Ashwin Sep 22, 2011 12:45 AM
# re: Dependency Injection With ASP.NET HttpModules
Hi Phil,
Thanks for your article. The one thing that we would lose by dynamically registering HttpModules is the ability to set preconditions for them without tinkering with IIS. Is there a way to programmatically set the preconditions for a HttpModule?

Thanks,
Ashwin
Requesting Gravatar... T Oct 19, 2011 9:35 PM
# re: Dependency Injection With ASP.NET HttpModules
When you register modules using code, how do you enforce the order of execution for the modules?

What do you have to say?

(will show your gravatar)
Please add 4 and 2 and type the answer here: