Dependency Injection in ASP.NET MVC 2 – Part 1: Controllers

28 February 2010 - 11:30 PM / by Dominic Pettifer. 3 Comments

Technical Article - In the first part of three, I show you how to perform Dependency Injection in ASP.NET MVC 2 using the Castle Windsor IOC (Inversion of Control) Container. In part 1 we look at injecting dependencies into your Controllers.

Dependency Injection

Using the principle of Dependency Injection, we can inject a concrete implementation into our ASP.NET MVC Controllers, but where the Controller only references an Interface not the concrete class. The benefits of this approach in a nut shell is that it allows us to decouple our codebase to make it more maintainable, and unit testable. Note the following contrived example:

public class ProductsController : Controller
{
   protected IProductsRepository ProductsRepository = null;

   public ProductsController(IProductsRepository productsRepository)
   {
      ProductsRepository = productsRepository;
   }

   public ActionResult ListProducts()
   {
      IList<Products> products = ProductsRepository.ListAllProducts();
      return View(products);
   }
}

Note we're using an IProductsRepository interface, but the concrete implementation might be an NHibernateProductsRepository or a LinqToSqlProductsRepository. We can use the IOC container to very easily swap out the implementation if we ever needed to change data access technologies, without changing any of the code that relies on the data access layer.

In the real world, obviously it's rare to change data access technologies during product development, but if you follow the DIP (Dependency Injection Principle) throughout your codebase, you'll inevitably find somewhere where you need to swap out implementations. The ability to swap implementations isn't the main reason to use DIP though, other reasons include allowing a more decoupled and maintainable codebase, and to facilitate unit testing. You could easily unit test the above code for instance, by injecting in a mocked IProductsRepository implementation, instead of one that needs to hit a database.

In the above example we're injecting the dependencies into the constructor (Constructor Injection), and indeed this is the recommended approach in most cases, as you’re saying that this class in dependant on this interface. But it's also possible to use Property Injection, just ensure the property is public.

If you're still unsure of the benefits of Dependency Injection, read up on the SOLID principles.

IOC with Castle Windsor

If you were to run the above code, it would throw an exception, because the way ASP.NET MVC instantiates Controllers, it expects there to be a default no-arg constructor.

Thankfully, Microsoft made the ASP.NET MVC framework extensible enough that we can change the way it instantiates Controllers. What we need to do is to get our IOC container, Castle Windsor, to instantiate the Controller. Castle Windsor will then automatically resolve any dependencies the Controller (or whatever it’s instantiating) has, such as the IProductsRepository type. Even better the IOC container can resolve any dependencies the dependencies themselves have, all the way down the dependency tree.

First create an IocHelper class:

public static class IocHelper
{
    private static IWindsorContainer _container = null;
    private static object _syncObject = new object();

    public static IWindsorContainer Container()
    {
        if (_container == null)
        {
            lock (_syncObject)
            {
                if (_container == null)
                {
                    _container = new WindsorContainer(new XmlInterpreter("ioc.xml"));
                }
            }
        }

        return _container;
    }

    public static void DisposeContainer()
    {
        if (_container != null)
        {
            lock (_syncObject)
            {
                if (_container != null)
                {
                    _container.Dispose();
                    _container = null;
                }
            }
        }
    }
}

This class provides a static accessor to our IOC container. We only ever instantiate a single container for the entire application lifetime.

Now ASP.NET MVC instantiates controllers using its own DefaultControllerFactory, we need to create our own Controller Factory that derives from DefaultControllerFactory and overrides the default controller instantiation behaviour:

public class IocControllerFactory : DefaultControllerFactory
{
    public IocControllerFactory()
    {
        var controllerTypes = from t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())
                              where typeof(IController).IsAssignableFrom(t)
                              select t;

        foreach (Type type in controllerTypes)
        {
            IocHelper.Container().AddComponentLifeStyle(type.FullName, type, LifestyleType.Transient);
        }
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType != null)
        {
            return (IController)IocHelper.Container().Resolve(controllerType);
        }

        return base.GetControllerInstance(requestContext, controllerType);
    }
}

The controller factory works by looking through the types in all the currently loaded Assemblies, and gets any that implement the IController interface, so you're free to carve up your Visual Studio Solution into whatever Projects you like, the IocControllerFactory will find your controllers. Looping through all types in all loaded Assemblies is a slow operation (about 50 milliseconds in my app), but it only happens once on start-up. The GetControllerInstance is responsible for instantiating the Controller for each HTTP request, and is instantaneous.

Next we need to register the new IocControllerFactory, do this in your web apps Global.asax.cs file:

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        // ... router registration code (snip) ... //
    }

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        ControllerBuilder.Current.SetControllerFactory(new IocControllerFactory());
    }
}

Now we need to create an XML file where we tell the IOC container what the concrete implementations are, eg. what is the concrete type for IProductsController. You may have noticed that in the IocHelper class we created the Container itself with the line:

_container = new WindsorContainer(new XmlInterpreter("ioc.xml"));

ioc.xml is the file where we specify the dependencies, located in the root of the web app folder. People sometimes put these in the web.config file, but I prefer keeping them separate to keep your web.config file nice and clean, we can also swap dependencies while the app is still running (modifying the web.config resets the web AppDomain).

Create an ioc.xml file next to your web.config file, then place the following into it:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <components>
    
    <!-- Repositories -->
    <component id="ProductRepository"
      service="MyMvcApp.Repository.IProductRepository, MyMvcApp"
      type=" MyMvcApp.Repository.Impl.NHibernateProductRepository, MyMvcApp"
      lifestyle="PerWebRequest">
    </component>
    <!-- End of Repositories -->

  </components>
</configuration>

Make sure the Namespaces and Assemblies are set according to your project. The 'service' attribute specifies the Interface or Abstract class (IProductRepository), 'type' specifies the concrete implementation to be used (NHibernateProductRepository).

If your concrete type has its own dependencies, you can specify them as well:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <components>

    <component id="NHibernateDataContextProvider"
      service=" MyMvcApp.NHibernate.INHibernateDataContextProvider, MvcLibrary"
      type=" MyMvcApp.NHibernate.Impl.WebSessionProvider, MvcLibrary"
      lifestyle="PerWebRequest">
    </component>

    <!-- Repositories -->
    <component id="ProductRepository"
      service="MyMvcApp.Repository.IProductRepository, MyMvcApp"
      type=" MyMvcApp.Repository.Impl.NHibernateProductRepository, MyMvcApp"
      lifestyle="PerWebRequest">
     <parameters>
        <ProviderFactory>${NHibernateDataContextProvider}</ProviderFactory>
      </parameters>
    </component>
    <!-- End of Repositories -->

  </components>
</configuration>

The 'lifestyle' specifies how long the concrete type is kept alive for, options are Transient, Singleton, PerWebRequest, Gay, Straight, and Hedonist (OK I made the last three up). PerWebRequest keeps the instance alive for the currently executing HTTP request, and is removed at the end. For this to work we need add an HttpModule to your web.config file for Castle Windsor to clear the instance at the end of the HTTP request like so:

<httpModules>
   <!— other modules, snip -->
   <add name="PerRequestLifestyle"
      type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.MicroKernel"/>
</httpModules>

Also add this module to the IIS 7 HttpModule section for running under IIS 7 on Windows Server 2008/Vista/7.

Repository Pattern

Don't forget your Repository implementation:

public class NHibernateProductsRepository : IProductsRepository
{
   protected INHibernateDataContextProvider SessionProvider = null;

   public NHibernateProductsRepository(INHibernateDataContextProvider dataContextProvider)
   {
      SessionProvider = dataContextProvider;
    }

   public IList<Product> ListAllProducts()
   {
      ISession session = SessionProvider.GetSession();
      return session.CreateCriteria<Product>().List<Product>();
    }
}

And the interface:

public interface IProductRepository
{
   IList<Product> ListAllProducts();
}

The Repository Pattern, coined by Martin Fowler (I think) in his book Patterns of Enterprise Application Architecture, is a way of decoupling your entities (Customer, Product etc.) from any data access code, and abstracting away the actual data storage implementation. Read more about it here or here.

Conclusion

Castle Windsor is a very powerful IOC container with many options for wiring up dependencies. Read more about Castle Windsor here.

There are other IOC containers out there for the .NET framework, for instance Ninject lets you specify your dependencies in code instead of verbose XML configuration files. Unity is an official Microsoft IOC container. Indeed there is more to the Dependency Injection Principle than I've been able to cover here, I encourage you to explore this very powerful paradigm in software engineering and write more elegant, maintainable and unit testable code.

In the next blog post I hope to cover wiring up dependencies during ModelBinding.

3 Comments on "IOC in MVC – Controllers"

Post a Comment
  • RE: IOC in MVC – Controllers

    "There are other IOC containers out there for the .NET framework, for instance Ninject lets you specify your dependencies in code instead of verbose XML configuration files."

    CastleWindsor also lets you do this. I used the following code for my own example:

    var container = new WindsorContainer();
    
    container.Register(Component.For<IRepository>()
                 .ImplementedBy<DefaultRepository>()
                 .LifeStyle.Singleton)
             .Register(Component.For<IValidator>()
                 .ImplementedBy<DefaultValidator>()
                 .LifeStyle.Singleton)
    
    ControllerBuilder.Current.SetControllerFactory(new IocControllerFactory(container));

    Posted on 1 June 2010 - 1:31 PM / by Alan

  • BD Connection

    I'm just wondering how do you manage your connection to a real time database. I am following other examples and I don't seem to get the database connection right for a real time example
    thank you
    (I hope my question es clear enough)

    Posted on 12 April 2010 - 1:23 AM / by Alvaro Romero Perez

    • RE: BD Connection

      Look in IOC.Data.RepositoryImpl.FakeCategoryRepository

      He's currently not using a database, but rather some factory to produce items.

      Like he mentioned, the implementation can easily be swapped out with one that work against a real database. That's the beauty of using a repository pattern and dependency injection.

      Posted on 2 May 2010 - 10:08 AM / by Krokonoster

Leave a Comment

Comment Details
*
* BBCode: [b]bold[/b], [i]italics[/i], [code]code[/code], [li]bullet point[/li], [h]Heading[/h], [url="http://www.example.com"]link[/url], [quote author="John Smith"]quote[/quote]

Random Image

James Bond pointing a gun.

Bond reveals a more human side to his character. (from the blog It’s Bond, But Not as You Know it )

Quick Poll

What is your DIP/IOC Container of choice?

Poll Vote
(see results)
View Comments (0) (See previous polls)

Latest Tweets

  • Red Bull gives you wings....that generate huge amounts of downforce #F1

    about 18 hours ago from Twitterrific
  • .vampire { -webkit-box-shadow: none; -webkit-box-reflection: none; } #cssjokes

    7:44 PM July 30th from Echofon
  • @edhenderson lol, lets get a trending topic going - .gangster .wrapper { color: #000; width: 150%; text-decoration: bling; } #cssjokes

    7:36 PM July 30th from Echofon
  • @weblivz I think the petition should be resubmitted but with security stuff taken out, as that's what the response purely focused on

    6:13 PM July 30th from Echofon
  • @weblivz I still think Chrome Frame can come to the rescue here, still keep their old browsers + legacy systems, no retraining costs etc.

    6:12 PM July 30th from Echofon

View Dominic Pettifer's Twitter page.