Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

ScottGu, Scott, Phil and Rob have announced a free ASP.NET MVC eBook and an open source ASP.NET MVC application Nerddinner.com. The free eBook is a single chapter of the Wrox’s upcoming title Professional ASP.NET MVC 1.0.  The free eBook provides an end-to-end walkthrough of building NerdDinner.com application. The free eBook and the free Nerddinner application are extremely useful if anyone is trying to lean ASP.NET MVC. If you are a beginner to ASP.NET MVC, I highly recommend checking the eBook and the NerdDinner.com application. You can download the NerdDinner.com application from here.

In this post, I am applying Dependency Injection to the NerdDinner.com application using Microsoft Unity Application Block. I was looking through the NerdDinner code and observed that controllers have Dependency Injection enabled constructors. So I can apply Dependency Injection through constructor injection without change any existing code. A Dependency Injection framework injects the dependencies into a class when the dependencies are needed. Dependency Injection enables looser coupling between classes and their dependencies and provides better testability of an application and it removes the need for clients to know about their dependencies and how to create them. If you are not familiar with Dependency Injection and Inversion of Control (IoC), read Martin Fowler’s article Inversion of Control Containers and the Dependency Injection pattern.  In this post, I am using Microsoft Unity Application Block for performing Dependency Injection pattern. Please check my blog post ASP.NET MVC Tip: Dependency Injection with Unity Application Block that demonstrated how you can use the Unity Application Block to perform Dependency Injection within an ASP.NET MVC application.

In this demo, I am doing constructor injection using Unity container. If a class instantiate using the Resolve method of the Unity container has a constructor that defines one or more dependencies on other classes, the Unity container automatically creates the dependent object instance specified in parameters of the constructor


Controller constructors and dependencies of NerdDinner application

Listing 1 – Constructor of DinnersController

 

   41  public DinnersController(IDinnerRepository repository) {

   42             dinnerRepository = repository;

   43         }

 Listing 2 – Constrcutor of AccountController

 

   26  public AccountController(IFormsAuthentication formsAuth, IMembershipService service) {

   27             FormsAuth = formsAuth ?? new FormsAuthenticationService();

   28             MembershipService = service ?? new AccountMembershipService();

   29         }

 Listing 3 – Constructor of AccountMembership – Concrete class of IMembershipService

 

  271 

  272         public AccountMembershipService(MembershipProvider provider) {

  273             _provider = provider ?? Membership.Provider;

  274         }

 
Dependencies of NerdDinner

DinnersController, RSVPController and SearchController have a dependency with IDinnerRepositiry. The concrete implementation of IDinnerRepositiry is DinnerRepositiry. AccountController has dependencies with IFormsAuthentication and IMembershipService. The concrete implementation of IFormsAuthentication is FormsAuthenticationService and the concrete implementation of IMembershipService is AccountMembershipService. The AccountMembershipService has a dependency with ASP.NET Membership Provider.

The below steps will configure Unity to perform constructor injection in NerdDinner 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 here. The Unity project is available in CodePlex at 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 demo, 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.

 

    1 using System;

    2 using System.Web;

    3 using Microsoft.Practices.Unity;

    4 

    5 namespace NerdDinner.IoC {

    6     public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable {

    7         public override object GetValue() {

    8             return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];

    9         }

   10         public override void RemoveValue() {

   11             HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);

   12         }

   13         public override void SetValue(object newValue) {

   14             HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue;

   15         }

   16         public void Dispose() {

   17             RemoveValue();

   18         }

   19     }

   20 }

 

 

Step 3 – Controller Factory for Unity and Register Types for Injection

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Linq;

    4 using System.Web;

    5 using System.Web.Mvc;

    6 using System.Web.Security;

    7 using System.Security.Principal;

    8 using NerdDinner.Models;

    9 using Microsoft.Practices.Unity;

   10 using NerdDinner.Controllers;

   11 namespace NerdDinner.IoC {

   12     public class UnityControllerFactory : DefaultControllerFactory

   13     {

   14         IUnityContainer container;

   15 

   16         public UnityControllerFactory(IUnityContainer container)

   17         {

   18             this.container = container;

   19         }

   20 

   21         protected override IController GetControllerInstance(Type controllerType)

   22         {

   23             try {

   24                 if (controllerType == null)

   25                     throw new ArgumentNullException("controllerType");

   26 

   27                 if (!typeof(IController).IsAssignableFrom(controllerType))

   28                     throw new ArgumentException(string.Format(

   29                         "Type requested is not a controller: {0}", controllerType.Name),

   30                         "controllerType");

   31                 return container.Resolve(controllerType) as IController;

   32             }

   33             catch { return null; }

   34 

   35         }

   36         public static void Configure() {

   37             //create new instance of Unity Container

   38             IUnityContainer container = new UnityContainer();

   39             //Register dependencies

   40             container.RegisterType<IFormsAuthentication, FormsAuthenticationService>();

   41             container.RegisterType<IMembershipService,AccountMembershipService>();

   42             container.RegisterInstance<MembershipProvider>(Membership.Provider);

   43 

   44             //Inject DinnerRepository for contract IDinnerRepository

   45             container.RegisterType<IDinnerRepository,

   46                 DinnerRepository>(new HttpContextLifetimeManager<IDinnerRepository>());

   47             ControllerBuilder.Current.SetControllerFactory(

   48                 new UnityControllerFactory(container));

   49         }

   50     }

   51 }

 

 

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.

The above Unity configuration specified in the Configure method tells that, to inject instance of DinnerRepositiry when there is a request for IDinnerRepositiry and  inject instance of FormsAuthenticationService when there is a request for IFormsAuthentication and inject instance of AccountMembershipService when there is a request for IMembershipService. The AccountMembershipService class has a dependency with ASP.NET Membership provider. So we configure that inject the instance of Membership Provider.


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

   29  void Application_Start() {

   30             RegisterRoutes(RouteTable.Routes);

   31             UnityControllerFactory.Configure();

   32         }

 

 

The above code will set the configuration for the Unity container when our ASP.NET MVC application is started. 

 

The source code of the new added files can be download from here

 

Published Thursday, March 12, 2009 6:33 AM by shiju
Filed under: , ,

Comments

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Friday, March 13, 2009 10:24 AM by Michael Hamrah

I'm curious why you're going with a custom HttpContextLifetimeManager rather than a ContainerControlledLifetimeManager for a singleton instance?  Will a singleton repository not work well with Linq To Sql?

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Friday, March 13, 2009 11:39 PM by shiju

@Michael Hamrah

I have used custom lifetime manager to store container in the current HttpContext. Since it is a web application I want to store container instance in my current HttpContext.

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Saturday, March 14, 2009 5:05 PM by Koistya `Navin

I use UnityControllerFactory from MvcContrib instead.

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Tuesday, April 7, 2009 1:48 AM by atmonline

shall i make a suggesion? can you please increase your font size. thanks. by the way congratulation for the baby girl.

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Wednesday, April 8, 2009 12:47 AM by shiju

@atmonline

Thanks for the suggesion.

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Monday, April 20, 2009 6:42 AM by Nik

Hi, thanks for this.

I'd prefer to keep my container's mappings in the web.config.  Registering the types has gone fine for all my types, except for this line :

container.RegisterInstance<MembershipProvider>(Membership.Provider);

Any idea how to register an instance like that in a .config line, instead of programatically?

Thanks.

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Wednesday, June 17, 2009 9:54 AM by Ervin Ter

Thank you very much. Solved my problem.

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Tuesday, August 25, 2009 2:03 AM by abilash

Hi Shiju Bhai,

  It seems that the implemetation of LifetimeManager using HttpContext is good enuf. But iam struck on a problem.HttpContextLifetimeManager.GetValue() method would throw null exception while the HttpContext.current is null. I am still investigation on when and how it goes null. Some scenarios were when any asynchronous delegates are called or when any other asynchronous calls are being made... Any idea on how to tackle this issue?

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Thursday, April 22, 2010 7:49 AM by raffaeu

Very well done, it's the perfect starting point of using IoC in MVC and it works like a charm!

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Monday, March 28, 2011 7:29 AM by weblogs.asp.net

Applying dependency injection in asp net mvc nerddinner com application.. He-he-he :)

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Thursday, June 2, 2011 5:51 PM by weblogs.asp.net

Applying dependency injection in asp net mvc nerddinner com application.. Dandy :)

# re: Applying Dependency Injection in ASP.NET MVC NerdDinner.com Application

Saturday, June 4, 2011 6:12 PM by weblogs.asp.net

Applying dependency injection in asp net mvc nerddinner com application.. Dandy :)

Leave a Comment

(required) 
(required) 
(optional)
(required)