Sunday, August 21, 2011

ASP.NET MVC 3 Dependency Injection

ASP.NET MVC 3 added some much needed improvements for dependency injection. With MVC 2, they wanted you to implement the IControllerFactory interface which provided some context and the name of the controller. Redirecting these method calls to a dependency injection framework wasn't hard, but support for DI in MVC 2 could have been better.

MVC 3 introduces the IControllerActivator and IDependencyResolver interfaces. An example implementation can be found here which uses Unity. I've shown you the relevant parts below:
internal class UnityDependencyResolver : IDependencyResolver
{
    private IUnityContainer _container = null;

    public UnityDependencyResolver(IUnityContainer container)
    {
        this._container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return this._container.Resolve(serviceType);
        }
        catch
        {
            // Return null to indicate that we were unable to create an instance
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return this._container.ResolveAll(serviceType);
        }
        catch
        {
            // Return null to indicate that we were unable to create an instance
            return null;
        }
    }
}
Then you just have to register this custom dependency resolver when your application starts.
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    // Register DI container
    ConfigureContainer();
}

private void ConfigureContainer()
{
    IUnityContainer container = new UnityContainer();

    // Register other services here

    // Set the current resolver
    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}

Nothing ground breaking here. It's the simplicity of it that makes it nice. What I really like is that almost everything is loaded through the current dependency resolver. So what does the IControllerActivator have to do with it? Well, I'm not sure to be honest. If you put a break point in a custom resolver at line 14, you'll see the following things attempting to be loaded:
  • IControllerFactory
  • IControllerActivator
  • HomeController (which controller you have set as your starting point)
  • IFilterProvider 
  • IViewEngine 
  • IViewPageActivator 
  • ... 
When I saw that my controller was being loaded by the dependency resolver. I wondered why I need to have a custom implementation of the IControllerActivator above? I removed my custom controller activator from my DI container and sure enough, my controller was created with dependencies and all. I'm sure there are cases where you may want to do some custom prepping before the controller handles the request. Except for those, I don't see that you need it.

So in the end, if you're using a respectable DI framework, IDependencyResolver is all you need.

2 comments:

  1. IDependencyResolver has a serious design flaw: No Release() method. See here:
    http://mikehadlow.blogspot.co.uk/2011/02/mvc-30-idependencyresolver-interface-is.html

    ReplyDelete
  2. Thanks for you comment. I read your blog posting on the issue and while I agree it's a shortfall, I would hardly classify it as a serious design flaw. There are too many workarounds for this to be considered serious.

    ReplyDelete