Dependency Injection in MVC 3

This post is part of the series I’m doing on the newly released ASP.NET MVC 3.

MVC was designed with loose coupling and testability in mind which has made dependency injection reasonably simple since day one.  The first version of MVC already shipped with an interface called IControllerFactory which was responsible for (you guessed it) locating and creating controllers.  Since the controller is usually the entry point into your MVC application this is where you would choose to hook into whatever dependency injection framework you’re using.

MVC 3 makes dependency injection a lot simpler – it’s built into the framework in a number of ways.  Firstly, it exposes an interface called IDependencyResolver which acts as a wrapper around pretty much any dependency injection framework.  Let’s take a look at how this works in practice.

How is it used

For this example I’m going to use Ninject as a dependency injection framework.  I usually prefer StructureMap, but someone on Twitter recommended Ninject so I’m going to try it out.

To work with the new IDependencyResolver interface I would usually have to write a wrapper around the dependency injection framework to implement this interface and then register that wrapper with MVC.  However, a wrapper for Ninject is already available on Nuget so I’m going to use that.  Simply type ‘install-package Ninject.MVC3’ in the Package Manager Console (View –> Other Windows –> Package Manager Console) and it will install both the wrapper and the Ninject framework for you.  Pretty cool.

As an example I’m going to write a simple controller that returns a list of products – pretty much the same example I used in my last post.

public class ProductController : Controller
{
    private readonly IProductRepository productRepository = new ProductRepository();

    public ActionResult Index()
    {
        var products = productRepository.GetProducts().ToList();

        return View(products);
    }

    public ActionResult Detail(int id)
    {
        var selectedProduct = productRepository.GetProducts().Single(p => p.Id == id);

        return View(selectedProduct);
    }
}

The ProductController here has a direct dependency on the ProductRepository class.  What I would like to do is register the ProductRepository as an implementation of the IProductRepository interface and then only reference the interface.

public class ProductController : Controller
{
    private readonly IProductRepository productRepository;

    public ProductController(IProductRepository productRepository)
    {
        this.productRepository = productRepository;
    }

    public ActionResult Index()
    {
        var products = productRepository.GetProducts().ToList();

        return View(products);
    }

    public ActionResult Detail(int id)
    {
        var selectedProduct = productRepository.GetProducts().Single(p => p.Id == id);

        return View(selectedProduct);
    }
}

Now we simply need to register this implementation with our dependency injection framework.  MVC will automatically inject this dependency when creating our controller.

public static void RegisterServiceLocator()
{
    // Create Ninject DI Kernel 
    IKernel kernel = new StandardKernel();

    // Register services with our Ninject DI Container
    RegisterServices(kernel);

    // Tell ASP.NET MVC 3 to use our Ninject DI Container 
    DependencyResolver.SetResolver(new NinjectServiceLocator(kernel));
}

public static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IProductRepository>().To<ProductRepository>();
}

If you run this code the ProductRepository will automatically get injected into our ProductController.  Cool stuff.

So what exactly did we gain here – all of this was already possible in MVC 2?  The only difference is that we need to implement IDependencyResolver to wrap our dependency injection framework instead of implementing our own ControllerFactory that does pretty much the same thing.  The difference is that our implementation of IDependencyResolver will now be used for instantiating every custom object we implement.

Dependency Injection for Filters

Dependency Injection has never been available for filters.  Keep in mind that filters are attributes and therefore created by the .NET runtime – we cannot use a traditional dependency injection strategy.  MVC 3 introduces the concept of filter providers – simply put our dependency injection framework can inject dependencies, but not through the constructor.

I’m going to implement a very simple MessageToAction filter that simply writes a message into the rendered view.  I would like this attribute to have a dependency on IMessageService – I want Ninject to inject the concrete implementation of this dependency.

public class MessageToActionAttribute : ActionFilterAttribute
{
    [Inject]
    public IMessageService MessageService { get; set; }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var actionName = filterContext.ActionDescriptor.ActionName;
        filterContext.Controller.ViewBag.FilterMessage = MessageService.GetMessageForAction(actionName);
    }
}

I need to explicitly tell Ninject to inject this property – as I mentioned we can’t do this through the constructor since attributes are created by the .NET runtime.  Now we need to do some extra plumbing to give Ninject a chance to perform the injection once our filters are created.

We need to register an instance of IFilterProvider – to make life a little easier I’m going to extend the built-in FilterAttributeFilterProvider class.

public class NinjectFilterProvider : FilterAttributeFilterProvider
{
    private readonly IKernel kernel;

    public NinjectFilterProvider(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        var filters = base.GetFilters(controllerContext, actionDescriptor);

        foreach (var filter in filters)
        {
            kernel.Inject(filter.Instance);
        }

        return filters;
    }
}

Now we need to register our filter provider with MVC.

FilterProviders.Providers.Add(new NinjectFilterProvider(kernel));

The last step is to register the concrete implementation of our IMessageService interface.

public static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IProductRepository>().To<ProductRepository>();
    kernel.Bind<IMessageService>().To<MessageService>();
}

And that’s it!  Dependency injection for action filters.  Pretty cool.

How to do this in MVC 2

You can’t really do this in MVC 2 – in the past I’ve always resorted to simply having a dependency on the concrete implementation.

Keep in mind that I’ve only illustrated one area where MVC 3 allows dependency injection.  With the changes in MVC 3 we can now do dependency injection in a number of areas – view engines, view pages, model validators, value providers, model binders – the list goes on.

I’m a little disappointed that MVC 3 doesn’t simply use the IDependencyResolver interface to do the kind of dependency injection I illustrated here – the need to create the filter provider is not ideal.  A feature for MVC 4 perhaps?

Further Reading

Brad Wilson did a series on dependency injection in MVC 3.  Just keep in mind that the first few posts were written with MVC 3 Preview 1 in mind – quite a few breaking changes were introduced with MVC 3 Beta.

Javier Lozano also did a post on dependency injection for filters in MVC 3.

You can download the code here.  Happy coding.

Tags: MVC, PatternsPractices