Click here to Skip to main content
15,884,472 members
Articles / Web Development / ASP.NET

How To Use Unity Container In ASP.NET MVC Framework

Rate me:
Please Sign up or sign in to vote.
4.74/5 (13 votes)
4 Aug 2010CPOL2 min read 79.6K   18   4
The article explains how to use Unity IoC container in ASP.NET MVC Framework.

Introduction

In the past, I wrote a post about How To Use Unity Container In ASP.NET.
In this article, I'm going to show and explain how you can use Unity IoC container in ASP.NET MVC Framework in order to make aspects in our application more decoupled.

Building The Container

As in the previous post, the first thing to do is to build the container itself. I'll use the same method that I used in the previous post in order to persist the Unity container’s state during the application execution. The right place to put the Unity container is as part of the Global.asax file as a property of the current running HTTP application. I'm going to use the same interface that I used in the past which looks like:

C#
public interface IContainerAccessor
{
    IUnityContainer Container { get; }
}

After the building of the interface, implement it in the Global class in the Global.asax file:

C#
public class MvcApplication : HttpApplication, IContainerAccessor
{
    #region Members

    private static IUnityContainer _container;

    #endregion

    #region Properties

    /// <summary>
    /// The Unity container for the current application
    /// </summary>
    public static IUnityContainer Container
    {
        get
        {
            return _container;
        }
    }

    #endregion

    #region IContainerAccessor Members

    /// <summary>
    /// Returns the Unity container of the application 
    /// </summary>
    IUnityContainer IContainerAccessor.Container
    {
        get { return Container; }
    }

    #endregion

    #region Application Events

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        InitContainer();
        ControllerBuilder.Current.SetControllerFactory(typeof(UnityControllerFactory));
    }

    protected void Application_End(object sender, EventArgs e)
    {
        CleanUp();
    }

    #endregion

    #region Methods

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );
    }

    private static void InitContainer()
    {
        if (_container == null)
        {
            _container = new UnityContainer();
        }

        // Register the relevant types for the 
        // container here through classes or configuration
        _container.RegisterType<IMessageService, MessageService>();
    }

    private static void CleanUp()
    {
        if (Container != null)
        {
            Container.Dispose();
        }
    }

    #endregion
}

The implementation is straightforward. You create a getter for the container which is a member of the HTTP application. Also in the application start event, I register all the relevant dependencies in the container and I dispose the container when the application ends.

The Unity Controller Factory

The real and important change with this new implementation of Global.asax is the setting of the controller factory which you will need to supply. The controller factory's responsibility is to instantiate the relevant controller for the incoming HTTP request. You should implement the IControllerFactory interface in order to be able to plug in your factory implementation.
The code for the UnityControllerFactory is as follows:

C#
public class UnityControllerFactory : IControllerFactory
{
    #region IControllerFactory Members

    public IController CreateController
	(RequestContext requestContext, string controllerName)
    {
        IContainerAccessor containerAccessor =
            requestContext.HttpContext.ApplicationInstance as IContainerAccessor;

        Assembly currentAssembly = Assembly.GetExecutingAssembly();
        var controllerTypes = from t in currentAssembly.GetTypes()
                              where t.Name.Contains(controllerName + "Controller")
                              select t;

        if (controllerTypes.Count() > 0)
        {
            return containerAccessor.Container.Resolve
			(controllerTypes.First()) as IController;
        }
        return null;    
    }

    public void ReleaseController(IController controller)
    {
        controller = null;
    }

    #endregion
}

The main thing to do is to implement the CreateController method of the IControllerFactory interface. I use the request context parameter to retrieve the current application instance and from it, I get the Unity container using the interface of IContainerAccessor. I also need to instantiate the relevant controller class which is being done by the Unity container for me.

The container will inject the dependencies in the controller by the Resolve method and we will get the dependency injection functionality that we wanted.

The Class to be Injected

I also wrote a MessageService which is a simple class that returns a message and inherit
from the IMessageService which declares the GetMessage method:

C#
public interface IMessageService
{
    string GetMessage();
}

public class MessageService : IMessageService
{
    #region IMessageService Members

    public string GetMessage()
    {
        return "Hello Controller!";
    }

    #endregion
} 

The Controller

The last piece in this puzzle is the controller class. I implemented the HomeCotroller class with the following code:

C#
[HandleError]
public class HomeController : Controller
{
    #region Members

    [Dependency]
    public IMessageService MessageService { get; set; }        

    #endregion

    #region Actions

    public ActionResult Index()
    {
        ViewData["Message"] = MessageService.GetMessage();
        return View();
    }

    public ActionResult About()
    {
        return View();
    }

    #endregion
}

The UnityControllerFactory will inject the dependency of the MessageService property with the relevant class and it's as simple as that. In order to run this, you'll have to create a new MVC framework application, add the classes I wrote and change the supplied HomeController to the implementation I wrote.

Summary

Let's sum up. I showed an example of how to use Unity container in ASP.NET MVC Framework application. This is a very simple example that will help you to get started with Unity in your MVC web applications.

History

  • 5th August, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead sparXys
Israel Israel
Gil Fink is a web development expert and ASP.Net/IIS Microsoft MVP. He is the founder and owner of sparXys. He is currently consulting for various enterprises and companies, where he helps to develop Web and RIA-based solutions. He conducts lectures and workshops for individuals and enterprises who want to specialize in infrastructure and web development. He is also co-author of several Microsoft Official Courses (MOCs) and training kits, co-author of "Pro Single Page Application Development" book (Apress) and the founder of Front-End.IL Meetup. You can read his publications at his website: http://www.gilfink.net

Comments and Discussions

 
QuestionGreat article ,Gil Pin
Shai Aharoni16-Jun-14 20:34
Shai Aharoni16-Jun-14 20:34 
GeneralMy vote of 2 Pin
yorro4-Dec-13 0:47
yorro4-Dec-13 0:47 
Good tutorial overall, but I have found a bug hence the rating of 2. It seems that your UnityFactoryController does not respect routing tables with multiple controllers having the same name but different areas.

Example of Error:

Lets say you have two controllers having the same name, but located in different areas.

1. MvcSample.Areas.Controllers.HomeController
2. MvcSample.Controllers.HomeController

Your UnityFactoryController pics up controller #1 using controllerTypes.First(), even though the request specifically identifies controller #2.

Solution

Here is a personal rendition that might solve the mentioned problem. I got it from here[^]
C#
using Microsoft.Practices.Unity;

public class UnityControllerFactory : DefaultControllerFactory
{
    private IContainerAccessor containerAccessor;

    public override IController CreateController(
        RequestContext requestContext,
        string controllerName)
    {
        this.containerAccessor =
            requestContext.HttpContext.ApplicationInstance as IContainerAccessor;

        var controllerType = GetControllerType(requestContext, controllerName);

        if (controllerType != null)
        {
            return containerAccessor
                .Container
                .Resolve(controllerType) as IController;
        }
        return null;
    }

    public override void ReleaseController(IController controller)
    {
        this.containerAccessor.Container.Teardown(controller);
        base.ReleaseController(controller);
    }
}


modified 15-Dec-13 0:15am.

GeneralMy vote of 5 Pin
jijinjnc22-Aug-11 23:20
jijinjnc22-Aug-11 23:20 
QuestionWhat if you place UnityControllerFactory somewhere else? Pin
jszczur5-Aug-10 23:04
jszczur5-Aug-10 23:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.