Unit tests, Test Driven Development, Behavior Driven Development, Inversion of Control, and Dependency Injection…. Whew! Don’t I sound smart!? These big dev words are concepts that many modern applications are using. TDD and BDD in particular are some great design patterns to help create “bug free code”.

Dependency Injection and Inversion of Control (DI and IoC) are two terms that mean relatively the same thing, and they are very useful when doing TDD, BDD, and just regular old unit tests. One of the things that can make testing complicated is when one thing depends on another thing.

public class HomeController : Controller
    {
        //
        // GET: /Home/
        private readonly IMyRepo _repo;

        public HomeController(IMyRepo repo)
             :this(new MyRepo()){
        }

        public HomeController(IMyRepo repo)
        {
            _repo = repo;
        }

        public ActionResult Index()
        {
            var stuff = _repo.GetStuff();

            return View(stuff);
        }

    }

The above code is known as “poor man’s dependency injection”. The basic point there being, when the default constructor of HomeController is called it shoves in a MyRepo object. This could be problematic during testing because if you need to mock or stub that object, you’d have to mess around with some stuff.

An easier and safer way to promote separation of concerns, another big word, is to use an actual DI framework such as Castle.Windor or Ninject .

I have used both, but this post will cover some Castle.Windsor stuff.

In order for Castle.Windsor to work, you will need to create a custom controller factory in some directory under your main project like Plumbing.

public class WindsorControllerFactory : DefaultControllerFactory
    {
        private readonly IKernel _kernel;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="kernel"></param>
        public WindsorControllerFactory(IKernel kernel)
        {
            _kernel = kernel;
        }

        /// <summary>
        /// Release the controller at the end of it's life cycle
        /// </summary>
        /// <param name="controller">The Interface to an MVC controller</param>
        public override void ReleaseController(IController controller)
        {
            _kernel.ReleaseComponent(controller);
        }

        /// <summary>
        /// Resolve a controller dependency
        /// </summary>
        /// <param name="requestContext">The HTTP context</param>
        /// <param name="controllerType">Type of controller to resolve</param>
        /// <returns>IController</returns>
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.",
                    requestContext.HttpContext.Request.Path));
            }
            return (IController)_kernel.Resolve(controllerType);
        }

    }

This will create instances of your controllers for you and throw a 404 error when the controller you are looking for does not exist.

Next up is the Installer for the controllers. Installers are how you tell Castle what to resolve when asked for some object. They inherit from IWindsorInstaller

public class ControllersInstaller : IWindsorInstaller
    {
        /// <summary>
        /// Installs the controllers
        /// </summary>
        /// <param name="container"></param>
        /// <param name="store"></param>
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(FindControllers().Configure(ConfigureControllers()));
        }

        /// <summary>
        /// Find controllers within this assembly in the same namespace as HomeController
        /// </summary>
        /// <returns></returns>
        private BasedOnDescriptor FindControllers()
        {
            return AllTypes.FromThisAssembly()
                .BasedOn<IController>()
                .If(Component.IsInSameNamespaceAs<HomeController>())
                .If(t => t.Name.EndsWith("Controller"));

        }

        /// <summary>
        /// Returns the transient lifestyle for the controllers.
        /// </summary>
        /// <returns></returns>
        private ConfigureDelegate ConfigureControllers()
        {
            return c => c.LifeStyle.Transient;
        }
    }

Then the Installer for the repository.

public class RepoInstaller : IWindsorInstaller
    {

        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(AllTypes.FromAssemblyNamed("YourAssembly")
                .Where(type => type.Name.EndsWith("Repo"))
                .WithService.DefaultInterface()
                .Configure(c => c.LifeStyle.Singleton));
        }
    }

And finally the code that ties it all together in Global.asax under Application_Start()

private static void BootstrapContainer()
        {
            var container = new WindsorContainer();     // Create a container to hold the dependencies
            var controllerFactory = new WindsorControllerFactory(container.Kernel);     // Create a new instance
            ControllerBuilder.Current.SetControllerFactory(controllerFactory);          // Use my factory instead of default

            container.Install(
                FromAssembly.This()
            );      // Scan this assembly for all IWindsorInstaller

        }

So, basically what we have done here is, now your controller code looks like this…

    public class HomeController : Controller
    {
        //
        // GET: /Home/
        private readonly IMyRepo _repo;

        public HomeController(IMyRepo)
        {
            _repo = repo;
        }

        public ActionResult Index()
        {
            var stuff= _repo.GetStuff();

            return View(stuff);
        }

    }

So, during the execution of your code when your HomeController get’s spun up, it will ask Castle.Windsor for an IMyRepo object. Then based on the RepoInstaller, it will find an object that implements RepoInstaller and automatically shove in a new MyRepo object.

Magical isn’t it!

 

4 Responses to Dependency Injection ASP.net MVC 3 Castle Windsor

  1. Jonathan,

    Thank you very much for providing such clear and to the point post. Most of what we see on the internet doesn’t explain in this clear manner.

    I was able to implement DI with Castle Windsor in my project using your guidance and it’s working great!

    All the best and keep up these great posts!

    Leniel

  2. PandaWood says:

    What makes you choose between where() and if()
    - In one you have .If(t => t.Name.EndsWith(“Controller”));
    - In another you have .Where(type => type.Name.EndsWith(“Repo”))

    I only ask because I was googling as to why I’m getting different results depending which of these 2 methods and which order I put them in.

  3. CD Smith says:

    ConfigureDelegate is an unknown class.. are there using statements that you aren’t showing that we need? It can’t resolve itself. I’m using Windsor 3

  4. leonard says:

    You can use next code:
    container.Register(FindControllers().Configure(c => c.LifestyleTransient()));

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>