Dependency Injection in ASP.NET MVC 3 using DependencyResolver and ControllerActivator

In my previous examples for dependency injection in ASP.NET MVC, I have used an approach where creating a custom controller factory deriving from DefaultControllerFactory and override the GetControllerInstance method for dependency injection. But ASP.NET MVC 3 is providing great support for dependency injection with very nice abstraction. In this post, I will demonstrate how to achieve dependency injection using two interfaces introduced in ASP.NET MVC 3 - IDependencyResolver and IControllerActivator. Unity 2.0 will be using as the dependency injection  container for this demo app.

Custom Controller Activator class using IControllerActivator

ASP.NET MVC 3 has introduced a new interface IControllerActivator which lets you activate controllers with custom behavior and can be use it for dependency  injection purpose.The IControllerActivator interface is discoverable using the dependency resolver. Let’s create a custom controller activator class by deriving from IControllerActivator intreface

  1. public class CustomControllerActivator : IControllerActivator
  2.     {        
  3.         IController IControllerActivator.Create(
  4.             System.Web.Routing.RequestContext requestContext,
  5.             Type controllerType)
  6.         {
  7.             return DependencyResolver.Current
  8.                 .GetService(controllerType) as IController;
  9.         }      
  10.     }

 Custom Dependency Resolver class using IDependencyResolver

ASP.NET MVC 3 has introduced a new interface IDependencyResolver which exposes two methods - GetService and GetServices.The GetService method resolves singly registered services that support arbitrary object creation and the GetServices resolves multiply registered services. Implementations of the IDependencyResolver interface should delegate to the underlying dependency injection container to provide the registered service for the requested type. When there are no registered services of the requested type, the ASP.NET MVC framework expects implementations of this interface to return null from GetService and to return an empty collection from GetServices. Let’s create a custom dependency resolver class by deriving from IDependencyResolver intreface in order to working with Unity to providing dependency injection.

 

  1. public class UnityDependencyResolver : IDependencyResolver
  2. {        
  3.     IUnityContainer container;       
  4.     public UnityDependencyResolver(IUnityContainer container)
  5.     {
  6.         this.container = container;
  7.     }
  8.  
  9.     public object GetService(Type serviceType)
  10.     {
  11.         try
  12.         {
  13.             return container.Resolve(serviceType);
  14.         }
  15.         catch
  16.         {               
  17.             return null;
  18.         }
  19.     }
  20.  
  21.     public IEnumerable<object> GetServices(Type serviceType)
  22.     {
  23.         try
  24.         {
  25.             return container.ResolveAll(serviceType);
  26.         }
  27.         catch
  28.         {                
  29.             return new List<object>();
  30.         }
  31.     }
  32. }

 Configure the Unity container with DependencyResolver.SetResolver Method

The below code in the Global.asax.cs configure the Unity container using SetResolver method of DependencyResolver class

  1. protected void Application_Start()
  2. {
  3.     AreaRegistration.RegisterAllAreas();
  4.     RegisterGlobalFilters(GlobalFilters.Filters);
  5.     RegisterRoutes(RouteTable.Routes);
  6.     IUnityContainer container = GetUnityContainer();
  7.     DependencyResolver.SetResolver(new UnityDependencyResolver(container));
  8. }

The SetResolver method of DependencyResolver class provides a registration point for dependency injection containers. In this method, we configure the UnityDependencyResolver class for providing dependency injection with Unity 2.0. The SetResolver method will be working with any dependency injection container.If you want to use StructureMap  as the dependency injection container, you can create a dependency resolver class in order to working with StructureMap  by deriving IDependencyResolver intreface and later you can configure this class with SetResolver method. The ASP.NET MVC 3 is providing an excellent support for working  with dependency injection containers.

The GetUnityContainer method is shown below

  1. private IUnityContainer GetUnityContainer()
  2.  {
  3.      //Create UnityContainer          
  4.      IUnityContainer container = new UnityContainer()
  5.      .RegisterType<IControllerActivator, CustomControllerActivator>()
  6.      .RegisterType<IFormsAuthenticationService, FormsAuthenticationService>()
  7.      .RegisterType<IMembershipService, AccountMembershipService>()
  8.      .RegisterInstance<MembershipProvider>(Membership.Provider)
  9.      .RegisterType<IDatabaseFactory, DatabaseFactory>(new HttpContextLifetimeManager<IDatabaseFactory>())
  10.      .RegisterType<IUnitOfWork, UnitOfWork>(new HttpContextLifetimeManager<IUnitOfWork>())
  11.      .RegisterType<ICategoryRepository, CategoryRepository>(new HttpContextLifetimeManager<ICategoryRepository>())
  12.      .RegisterType<IExpenseRepository, ExpenseRepository>(new HttpContextLifetimeManager<IExpenseRepository>())
  13.      .RegisterType<ICategoryService, CategoryService>(new HttpContextLifetimeManager<ICategoryService>())
  14.      .RegisterType<IExpenseService, ExpenseService>(new HttpContextLifetimeManager<IExpenseService>());
  15.      return container;         
  16.  }

 In the above GetUnityContainer method, I added the registration for IControllerActivator type into the Unity container along with other types. This will use concrete class CustomControllerActivator for the type IControllerActivator.

Source Code

You can download the source code from my demo app for ASP.NET MVC 3 and EF Code First at http://efmvc.codeplex.com/

12 Comments

  • Yea, I used the same approach with Unity, and I hate the fact that you need to resort to a try/catch to determine if Unity can resolve a given type. It seems like Ninject handles this specific case better with the TryGet which returns null.

  • @Alex: Unity 2.0 has IsRegistered method you can use to check existence before resolving, try...catch is no more the only option.

  • @TT Yea, but that only tells you if a given type is registered in the container. What it doesn't tell you is if the types it depends on is in the container.

    e.g. IF you're trying to resolve a controller like so:

    public HomeController(IRepository repo){}

    So in your DependencyResolver when trying to resolve the HomeController, Unity will tell you whether or now HomeController is Registered with with container, it won't however tell you whether or not it can actually resolve IRepository which is needed to successfully create a HomeContoller.

  • Do you think the following is a better implementation? All controllers are skipped from the IsRegistered checking.

    if (typeof(IController).IsAssignableFrom(serviceType))
    return _container.Resolve(serviceType);
    else
    return _container.IsRegistered(serviceType) ? _container.Resolve(serviceType) : null;

  • Nice post dude. It helped me a lot.

    What if we're making custom providers (e.g. session state store, membership, etc.) together with service/repository pattern, how can we configure the container to resolve dependency?

    Thanks!

  • I added only an empty Unity container to my application and it is still working fine.
    Is there a fall-back mechanism to the default resolver if the custom resolver cannot resolve a type?

  • Is it possible to do dependency Injection without any third party plugins such as Spring.NET or StructureMap?

  • I don't think you need to implement IControllerActivator. Just implement IDependencyResolver and take out the line ".RegisterType()"

  • Hi,
    I would like to seperate UI > service > Data, but bootstrapper need known assembly type for register data repositories which needs by services.
    suppose it;

    CustomerService get ctor injection ICustomerRepository
    ICustomerRepository need connection string but I dont want to know which connection string uses for CustomerService.

    How should I define repositories?

    Thanks

  • Really great article for beginners.. Thanks a lot

  • Really great article

  • wvlkcw I think this is a real great post. Want more.

Comments have been disabled for this content.