Do not implement IControllerActivator in ASP.NET MVC 3

ASP.NET MVC 3 introduces two new interfaces to allow simple integration of IoC containers into the MVC pipeline, allowing many different types to be resolved using your IoC container of choice. These interfaces are IDependencyResolver and IControllerActivator but before you go ahead and implement both, let's take a look at whether they are both actually needed.

First some background

If you wanted to inject dependencies into your controllers in ASP.NET MVC 2, you were required to either implement IControllerFactory or subclass DefaultControllerFactory. Typically, you would pass your IoC container into the constructor of your custom controller factory and use it to resolve the controller in the CreateController method. You may also have added custom code in ReleaseController to clean up dependencies.

This worked reasonably well, but in ASP.NET MVC 3 things have changed so we can use DI for a whole host of other objects such as filters and view engines.

The new interface that we should implement is IDependencyResolver:

public interface IDependencyResolver
{
  object GetService(Type serviceType);
  IEnumerable<object> GetServices(Type serviceType);
}

The important thing about your implementation of this interface is that it should return null if it cannot resolve a particular object. Below is a simple implementation using Unity:

public class SimpleUnityDependencyResolver : IDependencyResolver
{
  private readonly IUnityContainer _container;

  public SimpleUnityDependencyResolver(IUnityContainer container)
  {
    _container = container;
  }

  public object GetService(Type serviceType)
  {
    return _container.IsRegistered(serviceType) ? _container.Resolve(serviceType) : null;
  }

  public IEnumerable<object> GetServices(Type serviceType)
  {
    return _container.ResolveAll(serviceType);
  }
}

When an MVC application starts for the first time, the dependency resolver is called with the following types in the following order:

  1. IControllerFactory
  2. IControllerActivator
  3. HomeController
  4. ...

If you do not implement IControllerFactory or IControllerActivator, then the MVC framework will try to get the controller from the DependencyResolver itself. As a side note, there is no need to worry about performance (regarding so many calls to the resolver) because MVC will only try to resolve the IControllerFactory and IControllerActivator once on startup and if no implementations are registered then it will subsequently always query the DependencyResolver first.

The MVC framework goes on to try to resolve many other types which you probably have not implemented or registered with your IoC container, but as long as your dependency resolver returns null if the type is not registered, MVC will default back to the built-in implementations.

If you did not implement your resolver to return null if a type is not registered then you will probably end up seeing an error similar to:

The current type, System.Web.Mvc.IControllerFactory, is an interface and cannot be constructed.

The other important thing to note is that both methods on this interface take in the actual service type. This typically means that when you register your controllers with your IoC container, you should only specify the concrete type, not the IController, interface.

i.e. using Unity as an example:

container.RegisterType<HomeController>();

rather than:

container.RegisterType<IController, HomeController>(); // this will fail

Failing to register your controllers correctly and you will see:

No parameterless constructor defined for this object

So at this stage, we have an implementation of IDependencyResolver and nothing else and yet our controller are all resolving correctly. It makes you wonder about whether IControllerActivator is really needed....

About IControllerActivator

IControllerActivator was introduced with ASP.NET MVC 3 to split the functionality of the MVC 2 controller factory into two distinct classes. As far as I can tell, this was done to adhere to the Single Responsibility Principle (SRP). So now in MVC 3, the DefaultControllerFactory outsources the responsibility of actually instantiating the controller to the controller activator. The single method interface is shown below:

public interface IControllerActivator
{
  IController Create(RequestContext requestContext, Type controllerType);
}

If you implement this interface and register your activator with your IoC container, the MVC framework will pick it up and use it when trying to instantiate controllers, but you have to wonder why you would do this instead of just letting your dependency resolver do it directly. Brad Wilson to the rescue:

If your container can build arbitrary types, you don't need to write activators. The activator services are there for containers that can't be arbitrary types. MEF can't, but you can add [Export] attributes to your controllers to allow MEF to build them...

This means that if you are working with any competent IoC container* (Castle Windor, Unity, Ninject, StructureMap, Autofac et al), IControllerActivator is not needed and offers no benefit over allowing your DependencyResolver to instantiate your controllers.

* With the exception of MEF which isn't an IoC container any way

So we now know that we are probably not required to implement this interface, but are there any benefits to doing so? Something that I have seen mentioned (I cannot remember where) is that implementing IControllerActivator allows you you can provide a more meaningful error message if resolution fails. It is true that the message you would get otherwise (No parameterless constructor defined for this object) is not 100% clear, but I am not sure that this justifies another class just for this purpose. Surely, once you have seen this message, the next time you encounter, it you will immediately know what the problem is. Even if you do implement IControllerActivator, you will not have access to the (normally) detailed message that you IoC container provides when resolution fails, so you can do little more than say resolution failed - i don't know why.

Conclusion

So, should you implement IControllerActivator? Probably not. If you are using pretty much any well known IoC container, just implement IDependencyResolver and it will do everything for you. There is also no need for a custom implementation of IControllerFactory. If you are worried about the lack of release method on the dependency resolver, don't be. The worst case scenario requires a small change to the way that you are using your IoC container. Next time we will talk about how to make sure your dependency resolver plays nicely with IDisposable.

Comments

Avatar for Nizar Noorani Nizar Noorani wrote on 25 Apr 2011

If you want to inject in dependencies to your controllers, then you will need a custom activator. This also means that if you want to unit-test your controllers, then the cleanest way to do this would be create a custom activator. Otherwise, you MUST have a parameterless constructor for your controllers!

Avatar for Paul Hiles Paul Hiles wrote on 25 Apr 2011

@Nizar - No, that is not true. Custom activators are not necessary for all popular IoC containers - that is the whole point of the article. Your controller's constructor can have any number of parameters and as long as these dependencies are registered with the container, any decent implementation of IDependencyResolver will return your controller with all its dependencies satisfied. I have written many different MVC sites with 100% unit test coverage for the controllers without using controller activators. If you reread the article, you will find a quote from Microsoft's Brad Wilson confirming that activators are not required for most IoC containers.

Avatar for nabog nabog wrote on 07 Oct 2011

@paul, this is useful. But where it says "There is also no need for a custom implementation of IControllerFactory", I think should be qualified with "unless you want to hook into the MVC controller name resolution mechanism." Because IDependencyResolver.GetService(...) takes a type as a parameter, not a string like "Home" or "Account".

Avatar for Pop Catalin Pop Catalin wrote on 21 Feb 2012

@paul, IControllerActivator allows you to build and customize your controllers based on route data. If that is needed, then IControllerActivator the extension you will need (outside IControllerFactory), otherwise the simpler route is to implement IDependencyResolver.

Avatar for Mark P Mark P wrote on 03 Sep 2012

Know this is old - but agree with Pop Caitlin above - I am currently looking at how to implement routes for generic controllers in MVC 3 and see that the IControllerActivator may suit this purpose but yes for simple type scenarios there is no need for it.