• Blog
  • Archive
  • About
  • Contact
Sign in

Welcome to rickardnilsson.net

rickardnilsson.net is a weblog and the online home of web developer and father of three, Rickard Nilsson... More

Rickard blogs about creating software solutions using ASP.NET and agile practices.

Sites I've visited recently

  • Twitter
  • Facebook
  • Philip Wildenstam
  • Ninetech - Affärsnytta med IT
  • JetBrains ReSharper
  • Vimeo
  • dnrTV!
  • YUI Theater
  • BlogEngine.Net

Categories

  • .NET
  • Agile
  • ASP.NET 2.0
  • ASP.NET 3.5
  • ASP.NET MVC
  • BlogEngine.NET
  • C# 2.0
  • C# 3.0
  • CSS
  • Design by Contract
  • Design Patterns
  • JavaScript
  • TDD
  • Unit testing
  • User tip

Five most recent posts

  • Dependency injection in ASP.NET MVC with Unity IoC Container
  • ReSharper templates from the Code Kata Cast
  • How to unit test code which depends on HttpContext.Current.Server
  • Code Kata Cast
  • TDD Masterclass in the UK with Roy Osherove

Tag cloud

  • agile
  • ajax
  • asp.net 3.5
  • blog
  • blogengine.net
  • c#
  • code kata
  • css
  • dbc
  • dependency injection
  • design by contract
  • dom
  • douglas crockford
  • fakes
  • foto
  • getweekofyear
  • gregoriancalendar
  • highlight
  • html
  • httpcontext
  • humble dialog box
  • inversion of control
  • ioc container
  • iso 8601
  • javascript
  • jquery
  • jscript
  • julian bucknall
  • live template
  • metaweblog api
  • model-view-presenter
  • mvp
  • patterns & practices
  • photo album
  • picasa
  • recent posts
  • refactor
  • refactoring
  • release
  • resharper
  • rhino mocks
  • roy osherove
  • syntax
  • syntax highlighter
  • tdd
  • tdd masterclass
  • test coverage
  • testing
  • types
  • unit test
  • unity
  • web service
  • week
  • widget
  • word 2007
  • yahoo
  • yui

Recent comments

  • Code Kata Cast (8)
    Rickard wrote: @Marcus Eklund Classical music is royalty free sin… [More]
  • Code Kata Cast (8)
    Marcus Eklund wrote: http://creativecommons.org/ is a good place. Cl… [More]
  • Code Kata Cast (8)
    Rickard wrote: @Johan Lindfors Thanks! @Andrea I use TestDrive… [More]
  • Code Kata Cast (8)
    Marcus Eklund wrote: Nice one Rickard, A bit quiet though :P Used to t… [More]
  • Code Kata Cast (8)
    Andrea wrote: Nice one You can use the R# test runner and assig… [More]
<< ReSharper templates from the Code Kata Cast |

Dependency injection in ASP.NET MVC with Unity IoC Container

Friday, 25 December 2009 18:48 by Rickard

Enabling truly easy testability with ASP.NET MVC Controllers requires a Dependency Injection container. This post is about showing a more real life example of combining Unity with ASP.NET MVC Controllers than the standard demo. Unity is the IoC Container from Microsoft Patterns & Practices and ships as a part of Enterprise Library as well as a stand alone on Codeplex.

We start with the unit test which drives the design of the controller.

[TestMethod]
public void Post_PostWithSlugExists_ReturnsResultWithPostAsModel() {
    controllerContext.RouteData.Values.Add("slug", ValidSlug);
    var expected = MockRepository.GenerateStub<IBlogPost>();
    var blogPosts = new[] {expected};
    blogPostService.Expect(s => s.GetPostWhereSlugEquals(slug))
                   .Repeat.AtLeastOnce()
                   .Return(blogPosts);
    var controller = CreateController();

    var result = (ViewResult) controller.Post();
    Assert.AreEqual(expected, result.ViewData.Model);
}

Even though the test becomes a bit verbose it clearly states the intent of the controller’s Post method; given the right slug, a result is returned with a blog post as model.

Dependency Injection in ASP.NET MVC

In ASP.NET MVC every request starts in a controller which uses a set of dependencies to do its job. When we have applied Inversion of Control we can inject all of the controller’s dependencies either as a constructor argument or as a property setter. To fully take advantage of this technique we want the dependencies to be automatically injected without creating any of them in overloaded constructors or something like that. This is where the Controller Factory in ASP.NET MVC comes into play.

Controller Factory

In the System.Web.Mvc namespace lives the IControllerFactory which implementation is used by the framework to create controller instances. We can use this to swap out the default one and replace it with our own controller factory which uses Unity to create controllers instead.

Instead of implementing all of the IControllerF actory functionallity we can extend the System.Web.Mvc.DefaultControllerFactory and only override what we need.< /p>

public class UnityControllerFactory : DefaultControllerFactory {
    private readonly IUnityContainer container;

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

    protected override IController GetControllerInstance(Type controllerType) {
        return container.Resolve(controllerType) as IController;
    }
}

In the Global.asax, called MvcApplication in ASP.NET MVC by default, we create our Unity container and tells the MVC framework to use our UnityControllerFactory instead of the default one.

// in Global.asax.cs
protected void Application_Start() {
    RegisterRoutes(RouteTable.Routes);

    var container = new UnityContainer();
    var controllerFactory = new UnityControllerFactory(container);
    ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}

PostController

To illustrate why this is so powerful we will implement a controller that handles requests for blog posts, such as the one you’re reading right now. For this example the controller only handles requests for single blog posts using the post’s slug as identity. A slug is the post’s title made url friendly (e.g. "Dependency-injection-in-ASPNET-MVC-with-Unity-IoC-Container” for this post). The PostController has a dependency on an IBlogPostService which it uses to lookup the blog post to send to the view.

public class PostController : Controller {
    private readonly IBlogPostService blogPostService;

    public PostController(IBlogPostService blogPostService) {
        this.blogPostService = blogPostService;
    }

    public ActionResult Post() {
        var slug = GetSlug();
        var post = blogPostService.GetPostWhereSlugEquals(slug);
        return View(post);
    }

    private string GetSlug() {
        return RouteData.GetRequiredString("slug");
    }
}

Strongly-typed views

The Post action returns an ActionResult with the post a the model. We can use strongly-typed views to get intellisense in the aspx-file.

<%@ Page /*...*/ Inherits="ViewPage<IBlogPost>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    <%=Model.Title %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%=Model.Title %></h2>
    <p>
        <%=Model.Body %>
    </p>
    <p><%=Html.PostActionLink("Permalink", Model) %></p>
    <p><a href="/2009/10/10/fail">fail link</a></p>
</asp:Content>

Notice how the view inherits from ViewPage<IBlogPost> which is key to make the model type of IBlogPost. Then we can use the Post properties to render the blog post in the view.

Conclusion

Combining ASP.NET MVC with Unity or your IoC Container of choice makes your controllers much more easily testable. You only state your classes dependencies as constructor parameters or properties and the container will do the wiring for you. The gives you time to focus on the program logic and the interaction between its components.

Tags:   dependency injection, inversion of control, ioc container, unity, patterns & practices, testing
Categories:   Unit testing | ASP.NET MVC
Actions:  
Share | |

Related posts

How to unit test code which depends on HttpContext.Current.ServerMuch of the legacy ASP.NET code I’ve seen is littered with calls to methods on the HttpServerUtility...Syntax highlighting in BlogEngine.NETBlogEngine.NET ships with an extension that automatically highlights source code in blog posts. All ...Ny blog med BlogEngine.NET Hej! Kul att du tittar in. Jag har äntligen haft möjlighet att flytta min gamla blog fr&...
 
Copyright © 2008-2009 rickardnilsson.net