Archive for January, 2014

A different approach to dependency injection with ASP.NET MVC

No Comments »

If you read about dependency injection and ASP.NET MVC, what people are usually describing is constructor injection: all the dependencies of an ASP.NET MVC controller are provided through the constructor.

This has been bugging me for a while.  The problem is that, when you do traditional constructor injection, you end up with something like this:

public class HomeController : Controller
{
  public HomeController(IServiceA serviceA, IServiceB serviceB, IServiceC serviceC)
  {
    /* … */
  }

  public ActionResult ActionA()

  {
    /* uses serviceA */
  }

  public ActionResult ActionB()
  {
    /* uses serviceB */

  }

  public ActionResult ActionC()

  {
    /* uses serviceC */
  }
}

Notice how you end up having to pass all dependencies for all actions to the controller’s constructor. As the list of dependencies grows longer, and all these dependencies have to be instantiated every time ASP.NET MVC invokes an action, performance can suffer. Moreover, all those dependencies make writing unit tests tiresome, hurting developer productivity and code quality.

One way to mitigate the problem is to pass null or a dumb stub for the dependencies not used by a particular action under test. In other words, when testing ActionA(), just pass null or a stub for depencies serviceB and serviceC when instantiating the controller.

However, you can only do this because you are using implicit knowledge about the inner workings of ActionA(). If you change the implementation of the action, the dependencies might also change. In that case, everything will look the same from the outside, but unit tests will start failing.

So, ideally, what we want when testing an action method is to

  • only have to provide the dependencies actually used by the action method
  • have the dependencies of each action method be explicitly stated

Looking at this, it looks like what we want is to be able to write something like this:

public class HomeController : Controller
{
  public ActionResult ActionA(IServiceA serviceA)
  {
    /* uses serviceA */
  }

  public ActionResult ActionB(IServiceB serviceB)
  {
    /* uses serviceB */
  }

  public ActionResult ActionC(IServiceC serviceC)
  {
    /* uses serviceC */
  }

}

Here

  • the dependencies  of each action are very explicitly stated.
  • when unit testing an action method, we only have to provide the actual dependencies of that method.
  • as ASP.NET MVC has fewer dependencies to instantiate, performance is improved.

However, actions are invoked by the ASP.NET MVC framework, which knows nothing of our services, so how do we make this work?

As you probably know, ASP.NET MVC has a mechanism for providing arguments to action methods: model binding. In the default setup, model binding is used to turn HTTP data like query parameter values and form input into action method arguments. Fortunately, the model binding architecture is extensible. Thus, we can create our own model binder to provide the service dependencies:

public class DependencyResolvingModelBinder : DefaultModelBinder
{
  public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
  {
    return ShouldBeResolvedFromIOCContainer(bindingContext)
        ? DependencyResolver.Current.GetService(bindingContext.ModelType)
        : base.BindModel(controllerContext, bindingContext);
  }

  private static bool ShouldBeResolvedFromIOCContainer(ModelBindingContext bindingContext)
  {
    return bindingContext.ModelType.IsInterface;
  }
}

When this model binder is asked to provide a value for an action method argument that is an interface, it asks the IOC container to provide the value. In all other cases, it just falls back to the default ASP.NET MVC behaviour.

Configure ASP.NET MVC to use the new model binder by calling

ModelBinders.Binders.DefaultBinder = new DependencyResolvingModelBinder();

at the start of your application and presto! With just the few lines of code above, you can now write nice, clean action methods with well defined dependencies.

Enjoy writing those tests!


CLR Inside Out

No Comments »

My favourite column in MSDN Magazine was “CLR Inside Out”. Although it is a bit dated now, it is still a treasure trove of interesting information and geeky subtleties. If you haven’t done so already, you should check it out! I have compiled a table of contents for your convenience:

2010

2009

2008

2007

2006