June 2011 Blog Posts

What’s the Difference Between a Value Provider and Model Binder?

ASP.NET MVC 3 introduced the ability to bind an incoming JSON request to an action method parameter, which is something I wrote about before. For example, suppose you have the following class defined (keeping it really simple here):

public class ComicBook {
  public string Title { get; set; }
  public int IssueNumber { get; set; }
}

And you have an action method that accepts an instance of ComicBook:

[HttpPost]
public ActionResult Update(ComicBook comicBook) {
  // Do something with ComicBook and return an action result
}

You can easily post a comic book to that action method using JSON.

Under the hood, ASP.NET MVC uses the DefaultModelBinder in combination with the JsonValueProviderFactory to bind that value.

A question on an internal mailing list recently asked the question (and I’m paraphrasing here), “Why not cut out the middle man (the value provider) and simply deserialize the incoming JSON request directly to the model (ComicBook in this example)?”

Great question! Let me provide a bit of background to set the stage for the answer.

Posting Content to an Action

There are a couple of different content types you can use when posting data to an action method.

application/x-www-form-urlencoded

You may not realize it, but when you submit a typical HTML form, the content type of that submission is application/x-www-form-url-encoded.

As you can see in the screenshot below from Fiddler, the contents of the form is posted as a set of name value pairs separated by ampersand characters. The name and value within each pair are separated by an equals sign.

By the time you typically interact with this data (outside of model binding), it’s in the form of a dictionary like interface via the Request.Form name value collection.

The following screenshot shows what such a request looks like using Fiddler.

form-encoded-post

When content is posted in this format, the DefaultModelBinder calls into the FormValueProvider asking for a value for each property of the model. The FormValueProvider is a very thin abstraction over the Request.Form collection.

application/json

Another content type you can use to post data is application/json. As you might guess, this is simply JSON encoded data.

Here’s an example of a bit of JavaScript I used to post the same content as before but using JSON. Note that this particular snippet requires jQuery and a browser that natively supports the JSON.stringify method.

<script type="text/javascript">
    $(function() {
        var comicBook = { Title: "Groo", IssueNumber: 101 }
        var comicBookJSON = JSON.stringify(comicBook);
        $.ajax({
            url: '/home/update',
            type: 'POST',
            dataType: 'json',
            data: comicBookJSON,
            contentType: 'application/json; charset=utf-8',
        });
    });
</script>

When this code executes, the following request is created.

json-encoded-post

Notice that the content is encoded as JSON rather than form url encoded.

JSON is a serialization format so it’s in theory possible that we could straight deserialize that post to a ComicBook instance. Why don’t we do that? Wouldn’t it be more efficient?

To understand why, let’s suppose we did use serialization and walk through a common scenario. Suppose someone submits the form and they enter a string instead of a number for the field IssueNumber. You’d probably expect to see the following.

form-validation-error

Notice that the model binding was able to determine that the Title was submitted correctly, but that the IssueNumber was not.

If our model binder deserialized JSON into a ComicBook it would not be able to make that determination because serialization is an all or nothing affair. When serialization fails, all you know is that the format didn’t match the type. You don’t have access to the granular details we need to provide property level validation. So all you’d be able to show your users is an error message stating something went wrong, good luck figuring out what.

The Solution

Instead, what we really want is a way bind each property of the model one at a time so we can determine which of the fields are valid and which ones are in error. Fortunately, the DefaultModelBinder already knows how to do that when working with the dictionary-like IValueProvider interface.

So all we need to do is figure out how to expose the posted JSON encoded content via the IValueProvider interface. As I wrote before, Jonathan Carter had the bit of insight that provided the solution to this problem. He realized that you could have the JSON value provider deserialize the incoming JSON post to a dictionary. Once you have a dictionary, it’s pretty easy to implement IValueProvider and the DefaultModelBinder already knows how to bind those values to a type while providing property level validation. Score!

Value Provider Aggregation

The answer I provided only tells part of the story of why this is implemented as a value provider. There’s another aspect that was illustrated by my co-worker Levi. Sadly, for someone so gifted intellectually, he has no blog, so I’ll paraphrase his words here (with a bit of verbatim copying).

As I mentioned earlier, value providers provide an abstraction over where values actually come from. Value providers are responsible for aggregating the values that are part of the current request, e.g. from Form collection, the query string, JSON, etc.  They basically say “I don’t know what a ‘FirstName’ is for or what you can do with it, but if you ask me for a ‘FirstName’ I can give you what I have.”

Model binders are responsible for querying the value providers and building up objects based on those results.  They basically say “I don’t know where directly to find a ‘FirstName’, ‘LastName’, or ‘Age’, but if the value provider is willing to give them to me then I can create a Person object from them.”

Since model binders aren’t locked to individual sources (with some necessary exceptions, e.g. HttpPostedFile), they can build objects from an aggregate of sources. If your Person type looks like this:

public class Person {
  int Id { get; set; }
  [NonNegative]
  int Age { get; set; }
  string FirstName { get; set; }
  string LastName { get; set; }
}

And a client makes a JSON POST request to an action method (say with the url /person/edit/1234 with the following content:

{ 
  "Age": 30, 
  "FirstName": "John", 
  "LastName": "Doe" 
} 

   
The DefaultModelBinder will pull the Id value from the RouteData and the Age, FirstName, and LastName values from the JSON when building up the Person object. Afterwards, it’ll perform validation without having to know that the various values came from different sources.

Even better, if you wrote a custom Person model binder and made it agnostic as to the current IValueProvider, you’d get the correct behavior on incoming JSON requests without having to change your model binder code one tiny iota.  Neither of these is possible if the model binder is hard-coded to a single provider.

TL;DR Summary

The goal of this post was to provide a bit of detail around an interesting aspect of how ASP.NET MVC turns strings sent to a web server into strongly typed objects passed into your action methods.

Going back to the original question, the answer is simply, we use a value provider for JSON to enable property level validation of the incoming post and also so that model binding can build up an object by aggregating multiple sources of data without having to know anything about those sources.

ASP.NET MVC 3 Docs In Nine Languages

In May, we released a tools update for ASP.NET MVC 3 in nine languages other than English. Today I got the good news that ASP.NET MVC 3 documentation is also now available in those nine languages, which arguably is even more helpful to those learning and using ASP.NET MVC.

Our team is constantly working to improve the quality of our documentation and having docs available in multiple languages is a big part of that work.

Unfortunately, translation to Klingon is still not on the roadmap.

Update: For those wondering where the English documentation is, it’s here: http://msdn.microsoft.com/en-us/library/gg416514(v=VS.98).aspx

NuGet 1.4 Released

The moon goes around the earth and when it comes up on the other side, Hark! There’s a new release of NuGet! Well, this time it was more like one and a half revolutions, but I’m happy nonetheless to announce the release of NuGet 1.4.

A big thank you goes out to the many external contributors who submitted patches to this release! Your enhancements are much appreciated!

I’ve written up much more details about what’s in this release in the NuGet 1.4 Release Notes, but I’ll highlight a few choice things in this blog post.

NuGet Self-Update Notification Check

One thing you may notice immediately if you’re running NuGet 1.3 today is that the NuGet dialog notifies you itself that there’s a new version of NuGet.

NuGet Update Check Notification

Note: The check is only made if the Online tab has been selected in the current session.

This feature was actually added in NuGet 1.3, but obviously would not be visible until today, now that NuGet 1.4 is available.

Managing Packages Across The Solution

A lot of work in this release went into managing packages across the solution. If you’re a command-line junky, the Package Manager Console Update-Package commands now support updating all packages in all projects as well as a single package across all projects.

The NuGet dialog can also be launched at the solution level which makes it easy to choose a set of projects to install a package into, rather than installing a package into a project one at a time. This was a common request for those working on a large multi-project solution.

NuGet Project Selection

What’s Next?

This blog post is just a tiny sampling of what’s new. Again, check out the release notes for more details.

We’re going to try better to have a roadmap of the next couple of releases hosted on the front page here: http://nuget.codeplex.com/. For now, it’s very high level and general because we really only fully plan one iteration ahead.

However, we do have an idea of some of the big themes we want to focus on:

  • Simple package creation: We constantly want to lower the bar for creating and sharing code from inside and outside of Visual Studio.
  • NuGet in the Enterprise: This includes CI scenarios outside of Visual Studio, authenticated feeds, etc.
  • Flexible packaging: Includes things like including assemblies that are not referenced but deployed and vice versa.
  • Developer Workflow: We’re looking at common workflows that don’t match our own expectations and how we can support them. This also includes workflows we do know about such as the use of pre-release packages etc.

In general though, I think we can sum up all of themes in one big theme: Make NuGet Better!

Get Involved!

If you have great ideas for NuGet, please get involved in the discussions. We try to be very responsive and we do accept external contributions as Joshua Flanagan learned and wrote about in his blog post, An opportunity for a viable .NET open source ecosystem.

Then, remembering my last experience, I figured I would at least start a discussion before giving up for the night. To my surprise, the next day it was turned into an issue – this isn’t just another Microsoft Connect black hole. After hashing out a few details, I went to work on a solution and submitted a pull request. It was accepted within a few days. Aha! This is open source. This is how its supposed to work. This works.

Onward to NuGet 1.5!

Random Friday: On Turning Four

No, I’m not talking about my mental age.

My son turned four this past week which means I’m four years into my world domination plan. One of the gifts we gave my son was a toolbox with plastic toys so we can train him on building the mega-lasers and fortresses needed to take over the world. Turns out that before you start dominating the world, you have to start taking baby steps. And then toddler steps. And then 4-year old running terror steps.

In these past four years, I’ve learned a lot. For example, you can get a four year old to believe anything. That’s come in useful as a tool for manipulating my child to do my bidding. We were at the mall one day and he asked about a picture of a zombie with rotting teeth and without skipping a beat, my wife and I told him that’s what happens when you don’t wash your face and brush your teeth. There’s still complaining when I brush his teeth, but he’s at the sink at “two” on a three count.

Meta Bloggling

The point of this Random Friday series was to get back into the flow of blogging. But I am concerned that my Blog will turn entirely into random Friday blog posts. I guess it’s incentive for me to try and post some substance once a week as well. Or turn the knob down a bit and make this an every-other random Friday. The Fridays in between would be perfectly ordered and predictable Fridays and not worth blogging.

Friday Appreciation

And for the weekly thing I appreciate, it’s the sport of Soccer. Or Football as the rest of the world calls it. It’s interesting to me how quickly my British friends jump on me when I call it “Soccer”.

Bloody ‘ell! It’s called Football you stupid Amurrrrrican.

Which is ironic because the name Soccer comes from Association Football, which was invented, where else? England. The term was shortened to “Asoc” which forms the basis of the the word Soccer. In the words of those cheesy Anti-Drug PSAs, I learned it by watching you!

My summer soccer season started this Monday and we won our first game 5 – 4. Sadly, we went from 1st place in our division in the Winter season to last place last spring, which means we were relegated to a lower division for the summer season. Hopefully we can pull ourselves back up because things are a bit chippier down here.

After each game, I’ve somehow become the chronicler of our great deeds and I write-up a game report I send out to my teammates full of timeless sports classics such as Boom Goes The Dynamite. The fact that I have no future in sports writing is pretty safe. I toyed with the idea of posting the write-ups to my blog, but I didn’t want to turn my blog solely into a collection of Random Friday write-ups and tales of old men playing Soccer.

I’m on vacation next week so things should be quiet for me here. Unless past behavior is any indication in which case I’ll blog a thousand technical posts. Thanks for reading. Smile

Creating a Custom ASP.NET MVC Project Template

UPDATE: I have an example Really Empty project template up on GitHub you can look at. I improved on this technique a bit in that one.

When you create a new ASP.NET MVC 3 project, the new project wizard dialog contains several options for different MVC project templates:

There’s a lot of white space in that dialog. To many of you, all that unsullied territory smells like opportunity. When I talk about this dialog, I go to great pains to tell folks that, yes!, you too can extend that dialog and add your own project templates in there.

If you wanted to, you could have your own ASP.NET MVC 3 project template configured exactly the way you want. Hate the default template? Make your own!

The only problem is, I keep telling you that you can extend it, but sadly I never told you how. But that’s about to change!

    mvc3-project-wizard

I don’t expect that a large number of people will want to do this, which is one reason we haven’t spent a large amount of time making it easy (though that may change in the future). But for the few of you impatient masochists who want to add your own custom templates now, this blog post will walk you through the hacking around it takes to make it happen.

Imitation is the sincerest form of productivity

The easiest way to get started is to simply copy and modify an existing project template. For example, I looked in the following directory:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplates\CSharp\Web\1033

on my machine and stole *ahem* borrowed the project template named MvcWebApplicationProjectTemplatev3.01.cshtml.zip. Note that the 1033 folder is for English (en-US) templates. For other languages, you may need to look in a different folder.

I then renamed it to MyProjectTemplate.cshtml.zip and extracted the contents into a folder so I could make some modifications to its contents.

MyProjectTemplate.cshtml

When you extract the contents, you’ll want to rename the .vstemplate file to match the name of the template you chose. In my case, I renamed MvcWebApplicationProjectTemplatev3.01.cshtml.vstemplate to MyProjectTemplate.cshtml.vstemplate.

Open up the .vstemplate file in NotePad and make sure to change the TemplateID element value to something unique.

You can change any of the contents of the template folder now, but be very careful to make sure that any additions or deletions of content are reflected in the .vstemplate file. That file is a manifest of all the files within the VSIX package that makes up the project template. Also make sure that the .csproj file reflects those changes as well, to ensure any new files you add to the template are properly referenced in the project.

Pre-installed NuGet packages

UPDATE: The upcoming NuGet 1.5 feature will provide support for this feature in a way that doesn’t require the following harsh warning. Marcin Dobosz has a blog post detailing the feature.

Warning: I probably shouldn’t show you this next section and some of my co-workers may chide me on this. But if you promise to be responsible and pay close attention to the information and context for that information I’m about to show you, I’ll do it anyways and trust you not to inundate us with support calls when this blows your hand off.

The ASP.NET MVC 3 Tools Update includes very limited support for project templates that include NuGet packages. We originally wanted it to be very extensible, but ran out of time and imposed some severe limitations on the feature, hence the caution.

If you scroll to the bottom of the .vstemplate file, you’ll notice the following section:

<WizardData>
    <packages>
        <package id="jQuery" version="1.5.1" />
        <package id="jQuery.vsdoc" version="1.5.1" />
        <package id="jQuery.Validation" version="1.8.0" />
        <package id="jQuery.UI.Combined" version="1.8.11" />
        <package id="EntityFramework" version="4.1.10331.0" />
        <package id="Modernizr" version="1.7" />
    </packages>
</WizardData>

That is the list of NuGet packages that the MVC 3 project template installs when you invoke the project template.

But as I mentioned, there are two major limitations:

  • The package must exist in the %ProgramFiles%\Microsoft ASP.NET\ASP.NET MVC 3\Packages folder. MVC 3 doesn’t go searching online for them.
  • The version attribute of the package in the <package> element is required and is an exact match.

If you are fine with these limitations, you can modify this section of your custom project template to install the NuGet packages you care about. Just make sure they exist in the MVC 3 packages folder like I mentioned.

Once you are done making your changes, zip up the contents of the folder with the same file name you had before.

Registering your project template

At this point, all you need to do is copy the project template to the right location and add the appropriate registry entries. For extra credit, you can write an installer (MSI) that does all this for you.

The place to copy your template is the same place I mentioned previously, C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplates\CSharp\Web\1033

Once the template is there, you’ll need to setup the correct registry settings.

registry-editor

Since I’m lazy, I put these registry settings in a .reg file to make it easy to install. You’ll just need to modify the settings within the .reg file to match your project template.

32-bit

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\MVC3\
    ProjectTemplates\MyProjectTemplate]
"Title"="My Project Template"
"Description"="This is the coolest project template EVAR MADE."

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\
    MVC3\ProjectTemplates\MyProjectTemplate\C#\Razor]
"Path"="CSharp\\Web"
"SupportsHTML5"=dword:00000000
"SupportsUnitTests"=dword:00000000
"Template"="MyProjectTemplate.cshtml.zip"

64-bit

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\MVC3\
    ProjectTemplates\MyProjectTemplate]
"Title"="My Project Template"
"Description"="This is the coolest project template EVAR MADE."

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\
    MVC3\ProjectTemplates\MyProjectTemplate\C#\Razor]
"Path"="CSharp\\Web"
"SupportsHTML5"=dword:00000000
"SupportsUnitTests"=dword:00000000
"Template"="MyProjectTemplate.cshtml.zip"

The important thing to note are the options in the second registry section:

  • Path – Relative path from the ProjectTemplates folder. For C# projects, enter “CSharp\\Web”. For VB.NET use “VisualBasic\\Web”
  • SupportsHTML5 – Whether or not the project template supports HTML5. If set to 1, then the HTML 5 checkbox is enabled. That checkbox sets a project template variable, $usehtml5$. You can look at the default /Views/Shared/_Layout.cshtml inside of MvcWebApplicationProjectTemplatev3.01.cshtml.zip for an example of this.
  • SupportsUnitTests – This allows you to associate a unit test project template with your project template.
  • Template – the name of your project template file.

The last step is to run the command devenv /installvstemplates to force Visual Studio to recognize the project templates.

I wrote a batch file, install.bat, when combined with the .reg file, that automates these steps.

cd %~dp0
regedit.exe /s project-template.reg
xcopy MyProjectTemplate.cshtml.zip "C:\Program Files (x86)\Microsoft Visual Studio 
10.0\Common7\IDE\ProjectTemplates\CSharp\Web\1033"
/Y devenv /installvstemplates

For your convenience, I packaged up the necessary files in a zip file. Unzip the file, and run install.bat and you’ll see a new project template when you create a new ASP.NET MVC 3 project.

New ASP.NET MVC 3 Project

Pretty cool, eh?

By the way, I’m working on a book about ASP.NET MVC 3 with Brad Wilson, Jon Galloway, and K. Scott Allen. We’ve re-written large portions of the book in light of the new features that were released in ASP.NET MVC 3. If you’re interested, feel free to pre-order our book on Amazon.com!

Random Friday: My Accomplishments

It’s that time of year at Microsoft when managers are busily preparing reviews of their reports and preparing for the big stack ranking.

Yesterday, my manager sent out an email asking his reports to email him with their accomplishments in the past year to help jog his memory. This arms him with important information when he goes to the mat for us arguing why we’re more deserving of a higher ranking than some other manager’s sad report.

Here was my response. In the past year, I…

  • Escaped from a black hole. Twice. I forgot my jacket in there and had to go get it.
  • Discovered an albino polar bear.
  • Proved Fermat’s Last Theorem as well as his penultimate theorem.
  • Found Waldo. And made him change out of that ridiculous shirt and hat. Discovered he’s really Harry Potter.
  • Unified gravity and quantum mechanics while watching Jersey Shore to make it a challenge.
  • Invented cold fusion as well as luke warm fusion.
  • Passed the turing test using a computer made of legos.
  • Finished World of Warcraft on an Atari 2600.
  • Counted all the elements within an uncountable set of Hilbert spaces.
  • Hunted a magical unicorn with my bare hands. Drank its blood. And now I’m magical.

Not to be outdone, Steve Sanderson replied with the following:

Oh yeah? That’s nothing. I successfully submitted an expense claim using the online expenses tool.

Color me impressed!

Friday Appreciation

And for the weekly thing I appreciate, this week I appreciate the word hyperbole. It sounds like hyperbola, but is a totally different thing. Be sure not to confuse the two.

What I did above is hyperbole, while this is a hyperbola.

hyperbola

Have a nice weekend!

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.