ASP.NET MVC Tip: Dependency Injection with Unity Application Block

In my earlier post, I have explained how to use dependency injection pattern in ASP.net MVC application using StructureMap. In this post, I demonstrate how you can use dependency injection pattern using Microsoft’s Unity Application Block (Unity). If you want to develop an ASP.NET MVC application fully with Microsoft stack, you can use Unity Application Block to perform dependency injection.Unity is a cool dependency injection container and I hope that it will become more powerful in the future releases.

Introduction to Unity

Unity is a lightweight, extensible dependency injection container that provides the support for constructor, property, and method call injection. Unity has a service location capability that allows the ASP.NET developer to store or cache the container in the ASP.NET session, application or per Request.

Register Dependencies

Unity provides two methods for registering types and mappings with the container. The RegisterType method registers a type with the container and the RegisterInstance method registers with the container an existing instance of a type.

 

IUnityContainer container = new UnityContainer();            
container.RegisterType<ICategoryRepository, CategoryRepository>();

 

The above code tells the Unity Container that, to inject the instance of CategoryRepository when there is a request for ICategoryRepository and the container will create a new instance of CategoryRepository every time when there is request for ICategoryRepository. The default behavior is for the container to use a transient lifetime manager and the container will not store or cache a reference to the object. If you want singleton behavior for objects, you have to register a LifetimeManager. A lifetime manager controls how stores references to object instances and reused within the container.

 

IUnityContainer container = new UnityContainer();
    container.RegisterType<ICategoryRepository,
       CategoryRepository>(new ContainerControlledLifetimeManager());

 

The above registration specify that any time an instance of ICategoryRepository is requested, you will get back the same instance of CategoryRepository as long as the container is alive. The container will create a new instance at the time of first request and will be use the same instance for the later requests. The ContainerControlledLifeTimeManager class provides the singleton behavior for the container.

You can create your own custom LifetimeManager class derive from LifetimeManager class. The important methods of LifetimeManager class are GetValue that returns the instance, SetValue method store the instance value and RemoveValue method reomove the instance from the container.

public abstract class LifetimeManager : ILifetimePolicy
{
    public abstract object GetValue();
    public abstract void SetValue(object newValue);
    public abstract void RemoveValue();
}

Use Unity with an ASP.NET MVC application

In this tip, I show how you can use the Unity Application Block to perform Dependency Injection within an ASP.NET MVC application.  In this tip, I will show you how to perform constructor injection. Constructor Injection will push dependencies into a concrete class through constructor arguments.

The below code listings show that a controller class and its dependent classes.

 

Listing 1 – CategoryController

 

public class CategoryController : Controller {
       ICategoryService _categoryService = null;

        //Inject instance of CategoryService using construction injection
        public CategoryController(ICategoryService categoryService) {
            _categoryService = categoryService;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult List(int? page) {
            var categories = _categoryService.GetCategories(page ?? 0, 10);
            return View(categories);
        }
    }

Listing 2 – ICategoryService

 public interface ICategoryService {
    PagedList<Category> GetCategories(int pageIndex,int pageSize); 
    }

 

Listing 3 – CategoryService

  public class CategoryService : ICategoryService  {
         ICategoryRepository _repository = null;
        /// <summary>
         /// Creates a CategoryService based on the passed-in repository
        /// </summary>
         /// <param name="repository">An ICategoryRepository</param>
     public CategoryService(ICategoryRepository repository) {
            _repository = repository;
        if (_repository == null)
           throw new 
                 InvalidOperationException("Repository cannot be null");
        }

    public PagedList<Category> GetCategories(int pageIndex,int pageSize) { 
       return _repository.GetCategories().
         ToPagedList<Category>(pageIndex, pageSize); 
        }
    }

Listing 4 – ICategoryRepository

 

public interface ICategoryRepository {
        IQueryable<Category> GetCategories();       
    }

 

Listing 5 – CategoryRepository

public class CategoryRepository : ICategoryRepository  {

       myFinanceData _db;
        public CategoryRepository(myFinanceData data) {            
            _db = data;
            
        }

        /// <summary>
        /// Linq To Sql implementation for Categories
        /// </summary>
        /// <returns>IQueryable of Categories</returns>
        public IQueryable<Category> GetCategories() {

            return from c in _db.DataContext.Categories
                   select new Category {
                       ID=c.ID,
                       Name=c.Name,
                       Description=c.Description,
                       CategoryType = c.CategoryType
                   };

        }
   }

Listing 6 – myFinanceData

public  class myFinanceData
    {
        private myFinanceDataContext dataContext;

        public myFinanceDataContext DataContext {
            get {
                if (dataContext == null) {
                    dataContext = new myFinanceDataContext();
                }

                return dataContext;
            }
        }
    }

Depedencies

The CategoryController has a dependency with ICategoryService. The concrete implementation of ICategoryService, i.e. CategoryService has a dependency with ICategoryRepository. The concrete implementation of ICategoryRepository, i.e. CategoryRepository has a dependency with myFinanceData. When we calling action methods of Category controller, we need to create objects of CategoryService, CategoryRepository and myFinanceData.

The below steps will configure Unity to perform constructor injection in our ASP.NET MVC application.

Step 1 – Add reference for Unity Application Block

Add a reference to Microsoft.Practices.Unity.dll and Microsoft.Practices.ObjectBuilder2.

You can download Unity from http://www.codeplex.com/unity

Step 2 – Custom LifetimeManager class

Unity provides the functionality to specify the location of instance. This functionality is very useful for the ASP.NET applications where we can store or cache the container in the HttpContext, HttpSession or HttpApplication. In this tip, I used to store the container in current HttpContext.  In the below code, I am creating a custom lifetime manager to store container in the current HttpContext.

 

public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable {
        public override object GetValue() {
            return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
        }
        public override void RemoveValue() {
            HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
        }
        public override void SetValue(object newValue) {
            HttpContext.Current.Items[typeof(T).AssemblyQualifiedName]
                = newValue;
        }
        public void Dispose() {
            RemoveValue();
        }

Step 3 – Controller Factory for Unity

public class UnityControllerFactory : DefaultControllerFactory
{
    IUnityContainer container;

    public UnityControllerFactory(IUnityContainer container)
    {
        this.container = container;
    }

    protected override IController GetControllerInstance(Type controllerType)
    {
        try {
            if (controllerType == null)
                throw new ArgumentNullException("controllerType");

            if (!typeof(IController).IsAssignableFrom(controllerType))
                throw new ArgumentException(string.Format(
                    "Type requested is not a controller: {0}",
                    controllerType.Name),
                    "controllerType");
            return container.Resolve(controllerType) as IController;
        }
        catch { return null; }

    }
 }

 

The controller factory is responsible for creating controller instances.We extend the built in default controller factory with our own factory for working Unity with ASP.NET MVC.

 

Step 4 – Register Types and Set Controller Factory

public static class Bootstrapper {

    public static void ConfigureStructureMap() {

        StructureMap.StructureMapConfiguration.AddRegistry(new DBServiceRegistry());
        StructureMap.StructureMapConfiguration.AddRegistry(new DInjRegistry());


        IUnityContainer container = new UnityContainer();
        container.RegisterType<ICategoryRepository,
        CategoryRepository>(new ContainerControlledLifetimeManager());
    }
    public static void ConfigureUnityContainer() {
        IUnityContainer container = new UnityContainer();
        // Registrations
        container.RegisterType<myFinanceData, myFinanceData>
            (new HttpContextLifetimeManager<myFinanceData>());
        container.RegisterType<ICategoryRepository, CategoryRepository>
            (new HttpContextLifetimeManager<ICategoryRepository>());
        container.RegisterType<ICategoryService, CategoryService>
            (new HttpContextLifetimeManager<ICategoryService>());
        ControllerBuilder.Current.SetControllerFactory(
            new myFinance.Web.Controllers.UnityControllerFactory(container));           
    }
}

 

The above Unity configuration specified in the ConfigureUnityContainer method, tells to inject CategoryService when there is a request for ICategoryService. And also inject CategoryRepository when there is a request for ICategoryRepository. The CategoryRepository class has a dependency with myFinanceData. So we configure that inject the instance of myFinanceData when there is request for myFinanceData. The above code also set the controller factory for working with Unity.

 

Step 5 – Modify Global.asax.cs for configure Unity container

 

 protected void Application_Start() {
            RegisterRoutes(RouteTable.Routes);            
            //Configure for Dependecny Injection using Unity
            Bootstrapper.ConfigureUnityContainer();           
            
        }

The above code will set the configuration for the Unity container when our ASP.NET MVC application is started. The Bootstrapper class is specified in the Step 4.

Summary

In this tip, I demonstrated how you can use the Unity Application Block to perform Dependency Injection within an ASP.NET MVC application. The Unity Application Block allows us to develop highly loosely coupled ASP.NET MVC applications using fully with Microsoft stack.

12 Comments

  • I built out virtually the exact same structure over the weekend using Unity and with my own HttpRequestLifetimeManager. I am curious about having Unity create and store items that require disposing at the end of the HttpRequest however. Is there a way to ensure that the items are properly disposed of at the end of a request? My code and question with further details are at:

    http://www.codeplex.com/unity/Thread/View.aspx?ThreadId=38588


    I do like your lifetime manager a bit better, so I'll probably use that.

  • Nice article, very clear. Thanks

  • I built out virtually the exact same structure over the weekend using Unity and with my own HttpRequestLifetimeManager. I am curious about having Unity create and store items that require disposing at the end of the HttpRequest however. Is there a way to ensure that the items are properly disposed of at the end of a request? My code and question with further details are at:

    http://www.codeplex.com/unity/Thread/View.aspx?ThreadId=38588


    I do like your lifetime manager a bit better, so I'll probably use that.

  • I take a reference form your article to make my ASP.NET MVC application.
    I have a normal URL {controller}/{action}, In my actions, I need to use few services (but not using in same time) or some I don't need to use any service.
    So, I may a small changes from your guide as below could you please give your comments for my changes.

    public static class Bootstrapper {

    public static void ConfigureUnityContainer() {
    IUnityContainer container = new UnityContainer();
    // Registrations
    container.RegisterInstance(container);//Changes.
    container.RegisterType (new HttpContextLifetimeManager());
    container.RegisterType (new HttpContextLifetimeManager());
    container.RegisterType (new HttpContextLifetimeManager());
    ControllerBuilder.Current.SetControllerFactory(
    new myFinance.Web.Controllers.UnityControllerFactory(container));
    }
    }

    public class CategoryController : Controller {
    IUnityContainer container;

    public CategoryController(IUnityContainer container) {
    this.container= container;
    }
    ///
    ///
    ///
    ///

    ///
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult List(int? page) {
    ICategoryService _categoryService = container.Resolve(typeof(ICategoryService)) as ICategoryService ;
    var categories = _categoryService.GetCategories(page ?? 0, 10);
    return View(categories); }
    }

    public ActionResult DisplayXXX() {
    IXXXService _XXXService = container.Resolve(typeof(IXXXService )) as IXXXService ;
    var XXX= _XXXService.GetXXXs(page ?? 0, 10);
    return View(XXX); }
    }
    //No service request.
    public ActionResult Hello()
    {
    return view();
    }


    Thanks!
    Berlin.

  • You have a typo for the first example, Service should be Repository.

    Could you also do the same article for Autofac?

    Thanks!

  • How about providing an example with the Dependency Injection Framework MEF which is going to be part of .NET 4.0?

    thx
    jbe

  • Wow. Finally found a post that gives a step by step approach while giving a clear explanation of each step. Think I am good to go now, on using Unity with MVC. Thank you so much.

  • Great post... I was especially interested in setting up custom lifetimes for the ASP.NET request so your code example was exactly what I was looking for. I extrapolated it easily into a custom session-based lifetime as well.

    One thing that I was thinking about was unit testing. If I want to completely reuse my unity container for my test environment too (I guess to make sure things are resolving as expected) I would run into problems if I used the HttpContextLifetimeManager because it's ASP.NET specific.

    To tackle this I put an interface on the new lifetime manager (IHttpContextLifetimeManager) and registered the type with unity through the config. When registering other types that I want to use the HttpContextLifetimeManager I use Unity to resolve the manager. Now when running through ASP.NET it resolves to the actual HttpContextLifetimeManager, but in my tests I can have it resolve to a MockHttpContextLifetimeManager, which is a dummy implementation...

    This was the best I could come up with. Maybe I shouldn't be trying to reuse my unity container in my unit test environment... I'm now thinking that breaks some unit testing rules and I should just spin up a custom unity container on each test...

    Any thoughts on this approach?

    Thx, Joel

  • Thanks for the article, it's been very helpful. I've run into a problem where the HttpContextLifetimeManager Dispose never gets called. Have you run into this?

  • hi,Thank for your post! Excellent!!But Could you put it to download in High Definition, sbcauee it can't be seen so clearly in order to understand or if you send me the souce code too.Regards,Angel Santomas

  • If this were a 3 tier, then concrete CategoryService would be in the Business Tier and the concrete CategoryRepository would be in the Data Access Tier. So using the Unity Block like above would mean having to reference both libraries (DLL) in the MVC application. Or will the Unity Block sort out the indirect DLL references ? e.g. if I do a IOC such that the MVC application and the Data Access Tier, both refer the Business Layer DLL. So would I still need to refer the Data Access Layer DLL in the MVC application ?

  • ASP.Net appears to have a quirk with a set of label controls in a gridview row.

Comments have been disabled for this content.