in

Chennai .Net User Group

A platform that enables you to Learn, Share & Grow (India's first .Net user group)

Shiju Varghese's Blog

March 2009 - Posts

  • 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

     

  • ASP.NET MVC Tip: Add a new T4 template for making MVCContrib Grid Helper Component

    In this tip, I demonstrate how you can add a T4 scaffolding template within the “Add View” dialog of the ASP.NET MVC Framework. I am creating a List scaffolding template for MVCContrib Grid helper component. Earlier, I have blogged about how to use MVCContrib Grid helper component but recently the component has changed a lot and introducing a fluent interface  that provides a cleaner and more discoverable API. You can read all details from Jeremy Skinner's blog about the new enhancements of MVCContrib Grid helper component. I am creating the T4 template against the latest trunk of MVCContrib Grid helper.

    Overriding default T4 templates of ASP.NET MVC

    The default behaviour of T4 templates available in the  “AddController” and “AddView” dialog is machine-level. You can override the default T4 templates of ASP.NET MVC framework at per project level and also able to add additional templates within the “Add Controller” and “Add View” dialog. if you want override the global T4 tempates at project level, just copy the  C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC\CodeTemplates” folder into your ASP.NET MVC project. When you add T4 templates at project level, you should set the “Custom Tool” property of each of the T4 template files to an empty string value. Otherwise Visual Studio will try to transform the template so that you will get an error. The CodeTemplates folder contains two subfolders AddController and AddView and you can add new templates into this folders. If you add a new T4 template under the AddView folder, the new template will show in the "Add View" dialog. In this demo, I am adding a new template named MvcContribList.tt. For adding a new template within the Visual Studio, just add a text file and rename it with .tt extension.  

    AddView Dialog

     The Add View dialog shows the new added template MvcContribList in the View content list.

     

    I have taken the default List.tt template and modified it for creating the new template for working with MVCContrib Grid helper component. I have added the below code to working with MVCContrib Grid helper.

       59 <%= Html.Grid< <#= mvcHost.ViewDataType #> >(Model).Columns(column => {

       60  <#

       61     foreach(string propertyName in properties) {

       62  #>

       63 column.For(x => x. <#= propertyName #> ); <# } #>

       64 column.For(x => Html.ActionLink("Edit", "Edit", new { id = x.ID })).DoNotEncode();

       65 column.For(x => Html.ActionLink("Delete", "Delete", new { id = x.ID })).DoNotEncode();  

       66 })   

       67 .Attributes(style => "width:100%")

       68 .Empty("There are no records")

       69   %>

       70   <p>

       71     <%= Html.ActionLink("Create New", "Create") %>

       72    </p>

       73 <#

       74 }

       75 #>

     

    The source code along with a sample project available from here

    Summary

    In this tip, I demonstrated how to customizing and adding T4 templates and created a new T4 template for working with MVCContrib Grid helper component. You can easily override the global T4 templates of ASP.NET MVC framework and also able to add additional templates within the “Add Controller” and “Add View” dialog.

Copyright © 2002-2008 Chennai .Net User Group. All Rights Reserved. Microsoft and Microsoft logo's are trademarks of Microsoft Corporation