Published: 16 Mar 2010
By: Dino Esposito

In this article, I'll go through the process of customizing the controller factory to show that the controller name doesn't necessarily result from a token contained in the URL.

Contents [hide]

Introduction

Any URL that hits the ASP.NET MVC runtime environment has to be resolved in terms of a method to be invoked on a controller class. The name of the controller class and the name of the method - also known as the action - to be executed will be figured out in some way. As you may know, there's a default way that is hard-coded in the default Visual Studio template for an ASP.NET MVC application and there are changes you can make to machinery to have controller and action names result from a bit of applied logic. In this article, I'll go through the process of customizing the controller factory to show that the controller name doesn't necessarily result from a token contained in the URL.

Grabbing the Controller Name

When the default URL scheme is used, the controller name is the first token of the URL that follows the server name. Instead, if you opt for a custom URL routing scheme, identifying the controller name is up to you. The controller name may be one of tokens in the URL or it can be a fixed name or it may even be determined algorithmically. Strictly speaking, the controller name is not necessarily the name of the controller class. It is, instead, a moniker that is used to build the actual class name.

From the perspective of the ASP.NET MVC controller machinery the content of the URL may or may not be important for determining the controller name. What really matters is that an appropriate entry is found in the route dictionary packed with the name of the controller. The controller-specific entry in the route dictionary is named "controller". The ASP.NET MVC infrastructure will get it using the following code:

By default, the controller name is read from the URL and the controller class is built by adding a trailing Controller word to the controller name. Therefore, for a controller name of Home, the resulting controller type will be HomeController. As mentioned, this is just the default way of working. If necessary, an alternate approach can be found and implemented. In order of doing so, you need not just a custom route but also a custom route handler.

The following example demonstrates a custom route where the controller token is not specified explicitly, but results from the composition of two other tokens:

The URL scheme is completely custom and doesn't include any token that seems to represent the controller. The route value dictionary includes default values for the tokens in the URL template and not for any controller name. Yet a controller name has to be determined in some way.

The logic that determines the name of the controller class that will ultimately serve a request belongs to the route handler. It goes without saying that if you go for a custom route, you then need a custom route handler that incorporates just this logic. Here's some code for a custom route handler that works with the example:

A route handler is a class that implements the IRouteHandler interface. In the GetHttpHandler member of the preceding interface, the method first reads any route data that's available and then algorithmically determines the controller name to be used. When done, it adds it to the route data dictionary of the current request context. Finally, the updated request context is passed to the default ASP.NET MVC HTTP handler to serve the request. As an example, if the requested URL is http://server/blogs/home then the resolved controller name is something like Blogs_Home_ for a resulting controller type of Blogs_Home_Controller. The trailing Controller suffix is automatically added to the controller name if you stick to the default algorithm for getting the controller type as it is implemented in the DefaultControllerFactory class. By overriding the controller factory and the GetControllerType method on the factory, you could even change this aspect of the controller build up.

As a side note, consider that just as for the controller name, also the action name can be programmatically configured in case of a custom URL scheme. All you do is figuring out the name of the action by applying any necessary logic and then you store it in the RouteData collection under the key of "action".

Getting the Controller Type

You override the GetControllerType method if you want to change the naming convention applied to resolve the controller type. As mentioned, the default convention entails that the controller type name is whatever strings results from appending the word "Controller" to the controller name. You can change the default naming algorithm by creating (and registering) a new controller factory class:

It should be noted that the method returns a Type object that describes the class to instantiate later, not already an instance of the controller type. In addition, the assembly where the type is defined must be available in the current AppDomain. If the system couldn't find a type for the specified controller name then a runtime exception would be thrown.

Getting the Controller Instance

The GetControllerInstance method on the controller factory class is responsible for returning a concrete instance of the controller type that was found out by GetControllerType. The two methods are bound together in the implementation of CreateController in the default controller factory class.

You override the GetControllerInstance method when you need to change something in the way in which a controller is instantiated. Here's the implementation of the method in the DefaultControllerFactory class:

A common reason for replacing the controller factory and the way in which a instance is created is to enable dependency injection and enabling scenarios where the controller class receives a reference to the service layer class, the data access repository, or whatever other cross-cutting dependencies it may need. If for whatever reason the controller type is not configurable through the IoC, then the following code will still work:

The factory is also the place where you can add the code that configures any instance of a controller. This typically happens when you have a base controller class with custom properties. Another scenario is when you need to customize the action invoker.

Releasing the Controller Instance

The controller factory also exposes a method that takes care of the disposal of the controller instance. Most of the time, you don't need code significantly different from what the default implementation of the method in DefaultControllerFactory offers.

However, if your controller instantiates its own resources, that is a good place to get rid of them. When you employ an IoC container to create the controller instance you might also want to tear the instance down from the container. Here's the you need if you use Unity as your IoC.

When you use an IoC container to instantiate a controller you probably don't need more than a transient instance created on purpose for the request and disposed of at the end of the request lifecycle. However, a controller class may have injected via IoC a number of external objects some of which may have been configured with a different lifetime (i.e., singleton). In this case, disposing of them in ReleaseController may be too early and cause you troubles.

Summary

The creation of the controller is an important moment in the lifecycle of an ASP.NET MVC request. An ad hoc class - the controller factory - is responsible for getting you the controller instance to work with. You can define a constructor in your controller class to define some initialization steps or you can replace the default factory class. In doing so, you can take control of nearly any other aspects of the controller cycle including the identification of the type and disposal of the instance.

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

About Dino Esposito

Dino Esposito is one of the world's authorities on Web technology and software architecture. Dino published an array of books, most of which are considered state-of-the-art in their respective areas. His most recent books are “Microsoft ® .NET: Architecting Applications for the Enterprise” and “...

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

Other articles in this category


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...
jQuery Mobile ListView
In this article, we're going to look at what JQuery Mobile uses to represent lists, and how capable ...
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...
JQuery Mobile Widgets Overview
An overview of widgets in jQuery Mobile.
Book Review: SignalR: Real-time Application Development
A book review of SignalR by Simone.

You might also be interested in the following related blog posts


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
MvcContrib version control has moved to GitHub read more
How to use Ninject 2 with ASP.NET MVC read more
The ASP.NET MVC ActionController The controllerless action, or actionless controller read more
Going Controller-less in MVC: The Way Fowler Meant It To Be read more
ASP.NET MVC 2.0 and VS 2010 plan now public read more
Custom Controller Factory in ASP.NET MVC read more
Testability and TDD are not reasons to use the ASP.NET MVC Framework read more
Top
 
 
 

Please login to rate or to leave a comment.