DevTrends

MVC

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:

  • IControllerFactory
  • IControllerActivator
  • HomeController
  • ...
  •  

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 conrrectly 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.

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.

Useful or Interesting?

If you liked the article, we would really appreciate it if you would share it with your Twitter followers.

Share on Twitter »

Comments

Comments are now closed for this article.