New book: Programming Microsoft ASP.NET MVC

627147cvr.indd Dino Esposito’s first book on MVC, Programming Microsoft ASP.NET MVC, is now available for purchase! You can review the book’s TOC and Dino’s fascinating Introduction here. The book’s ISBN is 9780735627147, and its page count is 592 pages. And as you can see from the cover, the book covers ASP.NET MVC 2 and Visual Studio 2010.

In this post we offer an excerpt from the book.  We’ll get you two complete sample chapters in the near future.

Chapter 11

Customizing ASP.NET MVC

We need men who can dream of things that never were.
—John F. Kennedy

ASP.NET MVC was built with extensibility in mind and in full respect of many good design
principles, such as Dependency Inversion, Open/Closed, and Single Responsibility. As obvious
as it might sound, the net effect is just what these principles claim you will get if you apply
them systematically. You can extend the application without changing the source code,
without painful refactoring, and without heavy regression. If properly designed, your
application is then open for extensions but closed for modifications.

Because the Open/Closed principle is mostly a driver for architects and developers, the other
two principles provide concrete guidance on how to design classes that favor the injection
of custom components to replace built-in functionalities. The simpler and more well-defined
a class is, the easier it is for developers to customize and replace built-in functionalities. In
this regard, ASP.NET MVC is an excellent example of application design.

Because ASP.NET MVC is ultimately a framework, the benefits of its design will ripple
across any applications built on top of it. In this chapter, my goal is to help you discover the
points of extensibility you find in ASP.NET MVC and to illustrate them with a few examples.
I organized the extensibility points of ASP.NET into three main categories: execution of
actions, filters, and view rendering.

Note   For more information about the aforementioned design principles, often summarized
with the acronym SOLID, you can have a look at a recent book I wrote with Andrea Saltarello,
Microsoft .NET: Architecting Applications for the Enterprise (Microsoft Press, 2008). You might
find it curious that we don’t use the acronym SOLID anywhere in the text; however, the acronym
is a more recent (and nice) invention of some industry gurus. We do, though, cover exactly the
principles that contribute their initials to the acronym: Single Responsibility, Open/Closed, Liskov
Substitution, Interface Segregation, and Dependency Inversion.

The Controller Factory

I spent a lot of time and effort studying the internal implementation of ASP.NET Web Forms.
At the end of the day, any request that hits an ASP.NET Web Forms application is processed
by a class that derives from System.Web.UI.Page. This class implements the IHttpHandler
interface and does its work through the ProcessRequest method on the IHttpHandler
interface. Have you ever run across the implementation of this method?

ProcessRequest is a rather intricate mishmash of different programming styles, and it forms
a natural habitat for a number of common code smells: long method calls, endless branches,
switch statements, data clumps.

In ASP.NET MVC, any intercepted requests are routed to a new HTTP handler—the
MvcHandler class that you met already in Chapter 2, “The Runtime Environment.” This class is
designed to contain code functionally equivalent to the code in the ProcessRequest method
of the Web Forms’ Page class. The quality of the code in MvcHandler is significantly better—
it’s more readable, far easier to maintain and, in particular, extensible.

To understand the extensibility points of ASP.NET MVC, you have to start from controllers
and their factory. (And possibly also follow the example they provide in your own code.)

ASP.NET MVC Request Processing

On the way to controllers, the first stop is the MvcHandler class, where each ASP.NET
MVC request eventually lands. In Chapter 2, we briefly examined the source code of the
MvcHandler class with the purpose of explaining how an MVC request is processed. In this
context, we’ll get back to that source code with a different aim: to gain an understanding of
the mechanics and identify points of extensibility.

For simplicity, I’ll focus on the synchronous way of processing requests that is coded in
MvcHandler. For asynchronous calls, the same steps occur, but they are split in two distinct
phases—before and after the async point. (See Chapter 4, “Inside Controllers,” for more
details on asynchronous controllers and asynchronous request processing.)

Inside the MvcHandler Class

The core of an ASP.NET MVC request processing lies in the following code, which is invoked
directly by the ASP.NET runtime:

protected virtual void ProcessRequest(HttpContext httpContext)
    HttpContextBase contextBase = new HttpContextWrapper(httpContext);

In the first place, the original HTTP context is encapsulated in an HttpContextBase class to
decouple the rest of the code from the details of the HTTP runtime environment. These lines
of code are the key for mocking and testability, as discussed in Chapter 10, “Testability and
Unit Testing.”

The second call to ProcessRequest results in the following behavior:

protected virtual void ProcessRequest(HttpContextBase httpContext)
    IController controller;
    IControllerFactory factory;
    this.ProcessRequestInit(httpContext, out controller, out factory);

The controller in charge of the request is instantiated and configured in ProcessRequestInit.
Then it is given control over the request and released.

The Controller Builder

A first point of extensibility can be found in the ProcessRequestInit method, where the
process of instantiating the controller is abstracted to a factory. Here are some more details:

private void ProcessRequestInit(
    HttpContextBase context, out IController controller, out IControllerFactory factory)
    string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
    // Get the factory object for the controller
    factory = this.ControllerBuilder.GetControllerFactory();
    // Create the controller
    controller = factory.CreateController(this.RequestContext, requiredString);
    if (controller == null)
        throw new InvalidOperationException();

The key thing that is going on in the ProcessRequestInit method occurs in the invocation
of the controller builder. ControllerBuilder is a singleton class that holds the default
instance of the factory component in charge of creating controller instances:

public ControllerBuilder()
    . . .
    DefaultControllerFactory controllerFactory = new DefaultControllerFactory();
    controllerFactory.ControllerBuilder = this;

The default factory for controllers is the DefaultControllerFactory class. This class gets the
type of the controller class to instantiate and uses .NET reflection to activate it. In doing so,
it assumes a default constructor on the controller class and defaults to that.

The Default Controller Factory

As you can see in the preceding code snippets, the ControllerBuilder class encapsulates
an instance of the controller factory and makes it available through a pair of getter and setter
methods. In particular, the SetControllerFactory method is the tool you can use to unplug the
default controller factory and roll your own.

In Chapter 8, “The ASP.NET MVC Infrastructure,” I demonstrated how to leverage the
SetControllerFactory method to introduce an Inversion of Control (IoC)–based controller
factory that can automatically resolve the chain of dependencies rooted in the controller class.

You register your custom controller factory in Application_Start and have it kick in every time
a request is made:

protected void Application_Start()
    . . .
    // Create and register an IoC-based factory (using the Unity framework)
    var container = new UnityContainer();
    IControllerFactory factory = new MyAppControllerFactory(container);

At this point, the logic of the controller factory is up to you.

Even though a controller factory is abstracted to a specific interface—the IControllerFactory
interface—you probably want to start from the DefaultControllerFactory class to create your
own factory. At any rate, the IControllerFactory interface is shown here:

public interface IControllerFactory
    IController CreateController(RequestContext requestContext, string controllerName);
    void ReleaseController(IController controller);

The DefaultControllerFactory class implements the interface, but it also exposes overridable
methods at a slightly more granular level than the raw interface.

Extending the Default Controller Factory

In the DefaultControllerFactory class, the CreateController method is a two-step operation:
getting the controller’s type and getting an instance of that type. For both of these actions,
the DefaultControllerFactory class offers a ready-made virtual method. As a result, there are
three aspects of a controller factory that you might want to customize: getting the type for
the controller in charge of the current request, getting the controller instance, and releasing
the controller instance.

Here’s the list of methods on the DefaultControllerFactory class that you might want to override:

protected virtual IController GetControllerInstance(Type controllerType);
protected virtual Type GetControllerType(string controllerName);
public virtual void ReleaseController(IController controller);

Let’s examine each scenario in more detail.

Comments (1)
  1. Developers, Book excerpts, New books, ASP.NET, MVC says:

    Developers, Book excerpts, New books, ASP.NET, MVC

Comments are closed.

Skip to main content