Published: 07 Jan 2011
By: Manning Publications

This article is taken from the book Dependency Injection in .NET. Object Composition is one of three important dimensions of DI. ASP.NET MVC was designed with DI in mind, so composing an application is as easy as implementing a custom IControllerFactory and registering it with the framework.

Contents [hide]

About the book

This is a sample chapter of the book Dependency Injection in .NET. It has been published with the exclusive permission of Manning.


Written by: Mark Seemann
Pages: 375
Publisher: Manning
ISBN: 9781935182504

Get 40% discount

DotNetSlacker readers can get 40% off the full print book or ebook at www.manning.com using the promo code dns40 at checkout.

ASP.NET MVC was built with the express intent to be DI-friendly, and it is. It doesn't enforce the use of DI, but it easily allows it without making any assumption on the kind of DI you will apply. You can use Poor Man's DI or whichever DI Container you would like.

ASP.NET MVC extensibility

As is always the case with DI, the key to applying DI is to find the correct extensibility point. In ASP.NET MVC, this is an interface called IControllerFactory. Figure 1 illustrates how it fits into the framework.

Figure 1: When the ASP.NET MVC runtime receives a request, it asks its Controller Factory to create a Controller for the requested URL. The Controller Factory determines the correct type of Controller to use for the given request and creates and returns a new instance of that type. ASP.NET MVC then invokes the appropriate Action Method on the Controller instance. When it’s done, ASP.NET MVC gives the Controller Factory a chance to dispose of resources by calling ReleaseController.

When the ASP.NET MVC runtime receives a request, it asks its Controller Factory to create a Controller for the requested URL. The 

Controller Factory determines the correct type of Controller to use for the given request and creates and returns a new instance of that type. ASP.NET MVC then invokes the 

appropriate Action Method on the Controller instance. When it’s done, ASP.NET MVC gives the Controller Factory a chance to dispose of resources by calling ReleaseController.

Controllers are a very central concept in ASP.NET MVC. They handle requests and determine how to respond. If you need to query a database, validate and save incoming data, invoke Domain logic, and so on you initiate such actions from a Controller.

A Controller should not do such things itself but rather delegate the work to appropriate Dependencies. This is where DI comes in. We want to be able to supply Dependencies to a given Controller class, ideally by Constructor Injection. This is possible with a custom Controller Factory.

Creating a custom ControllerFactory

ASP.NET MVC comes with a DefaultControllerFactory that requires Controller classes to have a default constructor. That's a sensible default behavior that doesn't force you to use DI if you don't want to. However, default constructors and Constructor Injection are mutually exclusive, so we need to modify this behavior by implementing a custom ControllerFactory.

Doing so is not particularly hard. It requires you to implement the IControllerFactory interface:

The CreateController method provides you with a RequestContext that contains such information as the HttpContext, while the controllerName indicates which Controller is requested.

You may choose to ignore the RequestContext and just use the controllerName to determine which Controller to return. No matter what you do, this is the method where you get the chance to wire up all required Dependencies and supply them to the Controller before returning the instance. I'll show you an example in the subsection.

If you created any resources that need to be explicitly disposed, you get the chance to do that when the ReleaseController method is called.

Tip

DefaultControllerFactory implements IControllerFactory and has several virtual methods. Instead of implementing IControllerFactory from scratch, it is often easier to derive from DefaultControllerFactory.

Although implementing a custom ControllerFactory is the hard part, it's not going to be used unless you tell ASP.NET MVC about it.

Registering your custom ControllerFactory

Custom ControllerFactories are registered as part of the application startup sequence - usually in Global.asax. It is done by calling ControllerBuilder.Current.SetControllerFactory. Here's a snippet from the sample Commerce application.

In this example, we create and assign a new instance of the custom CommerceControllerFactory and pass it all the required and already created Dependencies. ASP.NET MVC will now use controllerFactory instance as its ControllerFactory for this application.

Example: implementing CommerceControllerFactory

The Commerce sample application needs a custom ControllerFactory to wire up Controllers with the required Dependencies. Although the entire dependency graph for all Controllers is considerably deeper, from the perspective of the Controllers themselves, the union of all immediate Dependencies is as small as three items, as shown in figure 2.

Figure 2: Dependency graph for the three Controllers in the sample Commerce application. The concrete implementations of each of these Dependencies have other Dependencies but these are not shown. BasketController and HomeController share a Dependency on CurrencyProvider. AccountController is inherited unchanged from the default ASP.NET MVC template; since it uses Bastard Injection it has no unresolved dependencies.

Dependency graph for the three Controllers in the sample Commerce application. The concrete implementations of each of these Dependencies have other Dependencies but these 

are not shown. BasketController and HomeController share a Dependency on CurrencyProvider. AccountController is inherited unchanged from the default ASP.NET MVC template; since 

it uses Bastard Injection it has no unresolved dependencies.

Each of these Dependency implementations encapsulate other Dependencies, but these are already wired up in Global.asax before they are passed to the CommerceControllerFactory, which itself uses Constructor Injection (see listing 1).

Listing 1: Initializing CommerceControllerFactory

This is the standard application of the Constructor Injection pattern for three Dependencies injected through the constructor, protected by Guard Clauses, and saved for later use in read-only fields.

Although we could implement IControllerFactory directly, it is easier to derive from DefaultControllerFactory and override its GetControllerInstance method. This means that the DefaultControllerFactory still takes care of mapping a Controller name to a Controller type, and all we have to do is to return instances of the requested types (see listing 2).

Listing 2: Creating Controllers

This method overrides DefaultControllerFactory.GetControllerInstance to create instances of the requested Controller types. If the requested type is either BasketController or HomeController, we explicitly wire them up with their required Dependencies and return them. Both use Constructor Injection so we supply the Dependencies through their constructors.

For those types not explicitly handled, we default to the base behavior, which is to create the requested Controller using its default constructor. Notice that we are not explicitly handling AccountController so we let the base behavior deal with it instead. AccountController is a carryover from the ASP.NET MVC project template and it uses Bastard Injection, which gives it a default constructor.

Note

I consider Bastard Injection to be an anti-pattern, but I left AccountController in that state because I had plenty of other proper DI examples to showcase. I did it because this is, after all, sample code, but I would never leave it like that in production code.

When a CommerceControllerFactory instance is registered in Global.asax, it will correctly create all requested Controllers with the required Dependencies.

Tip

Consider not writing a custom ControllerFactory yourself. Instead, use a general-purpose ControllerFactory that works together with your DI Container of choice. Take a look at the MVC Contrib project for inspiration, or simply use one of the reusable implementations available there.

The nice thing about ASP.NET MVC is that it was designed with DI in mind, so you only need to know and use a single extensibility point to enable DI for your application.

Summary

Object Composition is one of three important dimensions of DI (the others being Lifetime Management and Interception). Some frameworks make it easy for us. When writing console applications and Windows clients (WPF or Windows Forms) we are more or less in direct control of what is happening at the application's entry point. This provides us with a distinct and easily implemented Composition Root right at the entry point.

Other frameworks like ASP.NET MVC or WCF make us work a little harder but they still provide the Seams we can use to define how the application should be composed. ASP.NET MVC was designed with DI in mind, so composing an application is as easy as implementing a custom IControllerFactory and registering it with the framework.

Get 40% discount

DotNetSlacker readers can get 40% off the full print book or ebook at www.manning.com using the promo code dns40 at checkout.

<<  Previous Article Continue reading and see our next or previous articles Next Article >>

About Manning Publications

Manning Publication publishes computer books for professionals--programmers, system administrators, designers, architects, managers and others. Our focus is on computing titles at professional levels. We care about the quality of our books. We work with our authors to coax out of them the best writi...

This author has published 33 articles on DotNetSlackers. View other articles or the complete profile here.

Other articles in this category


jQuery Mobile ListView
In this article, we're going to look at what JQuery Mobile uses to represent lists, and how capable ...
JQuery Mobile Widgets Overview
An overview of widgets in jQuery Mobile.
jQuery Mobile Pages
Brian Mains explains how to create pages with the jQuery Mobile framework.
Code First Approach using Entity Framework 4.1, Inversion of Control, Unity Framework, Repository and Unit of Work Patterns, and MVC3 Razor View
A detailed introduction about the code first approach using Entity Framework 4.1, Inversion of Contr...
Exception Handling and .Net (A practical approach)
Error Handling has always been crucial for an application in a number of ways. It may affect the exe...

You might also be interested in the following related blog posts


Building Distributed Applications in ASP.NET MVC at MvcConf 2010 on 7/22/2010 read more
MSDN Guidance on ASP.NET MVC vs WebForms and its Impact on my EF + ASP.NET Work read more
Html Encoding Nuggets With ASP.NET MVC 2 read more
ASP.NET MVC2 Preview 2: Areas and Routes read more
MvcContrib working on Portable Areas read more
Auto-Start ASP.NET Applications (VS 2010 and .NET 4.0 Series) read more
Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 25: ViewModel read more
Video: DevExpress Plans For ASP.NET MVC read more
Walking the tight rope read more
MvcContrib version control has moved to GitHub read more
Top
 
 
 

Please login to rate or to leave a comment.

Free Agile Project Management Tool from Telerik
TeamPulse Community Edition helps your team effectively capture requirements, manage project plans, assign and track work, and most importantly, be continually connected with each other.