ASP.NET MVC Framework 2 Execution Process - Part 2

kick it on DotNetKicks.com
StumbleUpon.com
Save to delicious Saved by 0 users



This is my second post for the ASP.NET MVC Framework 2 Preview 2 with Repository - Part 1.  In this post, the ASP.NET MVC Framework 2 Execution Process will be looked into details.
  

Preface

Hi, there has been a long gap between my post on ASP.NET MVC Framework 2 Preview 2 with Repository – Part 1 and this one. In the first post, I haven’t touched on the ASP.NET MVC Framework particularly. Instead, I have focused on the MVC introduction, its history and its derivatives which I think is quite boring for most of the people. Most of the people will say why should care all about these pattern evolution since I can get myself directly into the ASP.NET MVC Framework. Well, you are right but most often we are confused over what are all these buzzwords about (MVC, Application Model MVC, MVP, Passive View, Supervising Controller and etc). People will ask what MVC is and how it is different from the ASP.NET MVC. ASP.NET MVC is Microsoft’s implementation on MVC pattern in its MVC Framework for .NET developers. In this post, I will devote fully to the Microsoft’s ASP.NET MVC Framework.

After the endless sequel of ASP.NET MVC 2 (ASP.NET MVC 2.0 Preview 1, ASP.NET MVC 2.0 Preview 2, ASP.NET MVC 2.0 Beta, ASP.NET MVC 2.0 RC, ASP.NET MVC 2.0 RC 2), ASP.NET MVC 2.0 RC 2 is probably the last unofficial release before its official release. Along the sequel, Microsoft has get feedback and incorporates bug fixes and enhancement in each of the sequence, but I don't bother so much because I don't have time to follow the progress and development. However, this is the time now as ASP.NET has come to its RC2 which is pretty stable now and will most probably become the official release for the upcoming release of Visual Studio 2010 and .NET Framework 4.0

ASP.NET MVC is not going to replace the ASP.NET Web Form (the model that was created more than 7 years ago). It is an option with ASP.NET. ASP.NET Web Form will continue to be the mainstream approach used when building ASP.NET application. Many of the good features in ASP.NET Web Form such as the postback, viewstate, server controls and etc have enabled building the common features for web application at ease particularly on building stateful web application over the stateless web medium. In addition, ASP.NET Web Form continues to be enhanced and improved in .NET Framework 4.0 with better viewstate management, Search Engine Optimization (SEO) improvement, URL routing, build in charting controls and much more). So, we can’t deny the importance of ASP.NET Web Form.
 
You may ask why ASP.NET MVC is introduced since the ASP.NET Web Form can do many things and fulfill our web application needs. Over the years, Microsoft has failed to emphasis the importance of architecture and software design patterns among the .NET web developers since the inception of ASP.NET 1.0. Along the way, Microsoft’s Patterns & Practices Group has released Web Client Software Factory to help and steer the .NET Architects and Developers to quickly incorporate many of the proven practices and patterns such as the MVC and MVP to build web forms application. However, it looks like far more complex for the average developers. Instead of driving the web forms to better design, Microsoft initiates a new ASP.NET MVC Framework to drive for better design, which I think Microsoft should have started 7 years ago. As in Java platform, we have the Struct Framework to build Java MVC web application which has been in existence for a long time. Anyway, it is never too late to have MVC Framework on ASP.NET now at least the .NET developers will have another option in .NET Framework 3.5 & 4.0 to write better and cleaner code for web application based on the MVC pattern that provides benefits of separation of concern and testability. For developers in the realm of TDD, this is good news as they can write better testable code with ASP.NET MVC as it is geared toward testability as Microsoft touts.


ASP.NET MVC

It is a web application framework based on the MVC pattern by Microsoft. I think there is no need for me to explain further on MVC generally as it is explained in depth in the first post here. You can refer to Wikipedia here to know more about its release history.

The ASP.NET MVC is defined in the System.Web.Mvc namespace and it is a lightweight and highly testable UI framework integrated well with the existing ASP.NET.

In brief, the Model retrieves and stores data. It comprises the business, data layers and any part of the application that handles the application domain logic. The View generates the output (Html pages) to reflect the model state change and the Controller handles user interaction such as process the user input as HTTP requests (GET and POST), operates on the Model in response to the request and select the View to render the result as HTML to the browser.

If the following are your primary concerns, then ASP.NET MVC is your best bet.


Separation of Concern

With the different aspects of the web application broken down into Model, View and Controller, it is easier to manage the complexity compared to the ASP.NET Web Form. Developer can focus on each aspect of the application without bothering the rest. For e.g. UX developer focus on developing the view without focusing on the Model at the same time. The task and responsibility of the development team can be clearly outlined and defined without overlapping each other.


• More control over the application behavior and needs

As the ASP.NET MVC does not rely on the postback, viewstate and server based controls. Developers will have far more better control over the application behavior. ASP.NET MVC is an extensible and pluggable framework; all of its component can be easily replaced or customized according to the needs. For e.g. developer can replace the view engine, routing policy, controller factory, route handler and etc at different stages of the MVC extensibility pipeline. You can click here to briefly know the different extensibility points in ASP.NET MVC.


Rich Routing Infrastructure

Use front controller pattern to process a web request through the controller which support rich routing infrastructure.


• Better TDD

As ASP.NET makes heavy usage of interfaces among the Model, View and Controller, it makes testing the individual component of MVC at ease because each of them can be tested in isolation of any framework. Mock objects can be easily created with any object mocking framework compatible with .NET framework and injected into the dependent component under testing. Compared with ASP.NET Web Form, carrying out unit testing is more cumbersome as it requires the developer to instantiate all the dependent classes in the individual pages. So, it is difficult to unit test individual part of the web application without getting all the real dependencies ready. Besides, carrying out unit testing for ASP.NET Web Form means spinning up the entire ASP.NET runtime. In other words, you have to import the whole System.Web assembly and invoke the complete request of a web application in your unit test project.

• ASP.NET MVC Supports of the existing ASP.NET features

All the existing features in the ASP.NET Web Form such as the forms and windows authentication, URL authorization, roles and membership, configuration system, the ASP.NET 2.0 provider model and etc are supported in ASP.NET MVC. The existing .aspx (ASP.NET Page), .asax (User Control File) and master pages are supported.

 
 
What are behind ASP.NET MVC?

Yeah. ASP.NET looks great based on what I have mentioned. What make it a great framework are all these .NET plumbing that works behind the scene. The crux of the ASP.NET MVC framework is the following three namespaces/assemblies as below

1. System.Web.Routing

This assembly/namespace is responsible for URL routing and enables us to use URLs that do not map to physical file. Types such as UrlRoutingModule, Route, RouteBase, RouteCollection and etc are in this namespace. In ASP.NET Framework 3.5 SP1, System.Web.Routing exists on its own in System.Web.Routing.dll assembly. Started in ASP.NET Framework 4.0, System.Web.Routing and all its types have been merged into the System.Web.dll assembly as shown in Figure 1.0


Figure 1.0 System.Web.Routing in .NET Framework 4.0



Within this assembly/namespace, there are a number of new classes under the System.Web namespace. This assembly is designed to wrap the ASP.NET’s core classes such as HttpContext, HttpResponse, HttpRequest and etc. In this assembly, you will find HttpContextBase, HttpContextWrapper, HttpResponseBase, HttpResponseWrapper, HttpRequestBase, HttpRequestWrapper and much more. HttpContextBase is actually an abstract base class that contains the same members as the HttpContext class. Whereas, the HttpContextWrapper extend the HttpContextBase and it is a wrapper for the HttpContext. HttpContextWrapper is a form of Adapter pattern which actually adapts the HttpContext class to the HttpContextBase abstract class. Within the HttpContextWrapper, there is internal field which is of type HttpContext class pointing to the HttpContext instance passed from the constructor of HttpContextWrapper during its instantiation. HttpContextWrapper merely delegates the work to HttpContext. The rationale behind is to enable easier unit testing as we can use any object mocking framework for .NET framework to create mocked implementation of the HttpContextBase class for the purpose of unit testing. Most of the ASP.NET core classes are static or sealed such as HttpContext. They are harder to test because they can’t be easily mocked or stubbed with the object mocking framework. There is an article here demonstrated by Justin Etheredge on how to mock against the HttpContextBase class in the unit tests with the Moq object mocking framework. You can also follow my post on Using Mocking Framework - Moq which demonstrates how to apply the Moq object framework in your unit tests project.

This assembly exists to ensure the testability of ASP.NET MVC because if we were to write all the wrappers for the different ASP.NET’s core classes, it would be a nightmare for the developers. In .NET framework 4.0, the classes/types in the System.Web.Abstractions (.Net framework 3.5 Sp1) have been merged into the System.Web namespace in the System.Web.dll assembly as shown in Figure 1.1


Figure 1.1 Some Wrappers for ASP.NET’s Core Classes


3. System.Web.Mvc

This assembly contains all the classes and interfaces to support the creation of MVC web application. Within this assembly you can find class like System.Web.Mvc.Controller, System.Web.Mvc.ControllerBase, System.Web.Mvc.ActionResult, System.Web.Mvc.ViewPage and so on and so forth to support the MVC application project. You will encounter most of them when you build the MVC project.


 
ASP.NET MVC Framework 2 Execution Process
 
First, we are going to look at the URL Routing. This feature is provided in the System.Web.Routing. Before we go on further let us look at the following Figure 1.2 which depicts the execution process of the ASP.NET MVC application.


Figure 1.2 ASP.NET MVC Application Execution Process

ASP.NET MVC application uses URL routing functionalities provided in the System.Web.Routing to accept request URLs that do not map to physical files in the web site. In fact, with ASP.NET URL Routing, user can define the criteria of mapping the URL requests to the logical resources in a way that is semantically meaningful to the web users. In other words, ASP.NET routing decouples the URLs from the physical files and enables us to expose clean and SEO-friendly URLs. Hence, it improves page hits by putting the relevant keywords into the URL. Furthermore, it also works well with the representational state transfer (REST).

With ASP.NET URL Routing, the URL for a traditional page that displays customer information might look something like follow;

http://localhost/Customer.aspx?Id=5

However, using the ASP.NET Routing, we can configure the application to accept the request via the following URL

http://localhost/Customer/5

ASP.NET URL Routing was first introduced in the ASP.NET 3.5 SP1. However, the ASP.NET Routing is not the sole proprietary of ASP.NET MVC application. It can be used in the ASP.NET Web Form application as well. That why, the functionalities are independent of the System.Web.Mvc assembly. In .NET Framework 4.0, the System.Web.Routing namespace and its types have been merged into the System.Web.dll assembly. When you build a web application targets .NET framework 4.0, whether it is ASP.NET Web Form or ASP.NET MVC application, the ASP.NET Routing functionalities will be immediately available because the System.Web.dll is always automatically referenced in the web application project.

Some of you may ask what is the difference between URL rewriting and ASP.NET URL Routing? There is a great article; IIS URL Rewriting and ASP.NET Routing elaborates this in detail.

Let see what is going on when a URL request comes from a browser based on the Figure 1.2. The explanation below is actually a much simplified overview of the execution process where in the real life, the whole process is much more complex and some of the details are being left out below. For e.g. some of the processes/events of HttpApplication that take place before the execution is transferred to the UrlRoutingModule. There is an article from Microsoft here explains the events in IIS 7 in depth.


a) The URL request comes to the ASP.NET MVC application. The System.Web.Routing.UrlRoutingModule also called the routing engine which implements the System.Web.IHttpModule interfaces will first match the URL request to its System.Web.Routing.RouteCollection property to find the first System.Web.Routing.Route object that matches the current URL request. In the Route object, URL pattern that you want to map a class that handle requests correspond to the pattern is defined. This will enable the UrlRoutingModule to return the first most appropriate Route object. If no Route object that has the URL pattern that matches the URL request, the UrlRoutingModule does nothing and the request will be processed as a normal ASP.NET or IIS request. Let say if there is http request for form1.aspx and it happens that form1.aspx exists as a physical file on the disk; URLRoutingModule will also ignore the route lookup. This is the UrlRoutingModule’s default behavior.

In order for the UrlRoutingModule to have Route objects to match the URL request, the System.Web.Routing.RouteTable exposes a RouteCollection via its public static Routes collection property. This Routes collection is where we configure our custom routes before the ASP.NET MVC application starts to accept URL request. The best place to configure the custom routes is in the Global.asax within the Application_Start event as shown in Figure 1.3

 
 
Figure 1.3 Configure Your Custom Routes in Global.asax and Application_Start Event

As shown in Figure 1.3, this is the default route that will be added by the ASP.NET MVC project into your Global.asax file. You can define your own custom route with different URL pattern. The default route as shown in Figure 1.3 will match a URL pattern with three segments which consists of controller, followed by an action method and an id. The following URL request will match the default route;
 
 
http://localhost/Customer/Edit/2
 
 
The segment is embraced in the curly braces {}, and it will be captured and used later in the route handler. If we adopt the convention of creating controller by inheriting from the System.Web.Mvc.Controller (when you create a new controller from the Visual Studio 2008/2010’s Add Controller Dialog as shown in Figure 1.4 ), then the first segment of the URL, Customer will map to CustomerController, the second segment Edit will map to the action method, Edit in the CustomerController class and the third segment, 3 will be treated as a parameter to the action method Edit.
 
 
Figure 1.4 Add Controller Dialog Box (Right Click on Controllers Folder in Solution Folder and Select Add -> Controller)
 
 
Notice that the third parameter to the MapRoute extension method in the public static method, RegisterRoutes() is an anonymously type object constructed to represent the default values for the UrlRoutingModule to use if it can’t find a given parameter in the URL.
 
 
b) Let assume that the user requests the URL, http://localhost/Customer/Edit/2 from the browser, now the UrlRoutingModule has selected the first System.Web.Routing.Route object in its RouteTable’s Routes collection property, which is the default route. From the matching Route object, the UrlRoutingModule can retrieve an object that implements the System.Web.Routing.IRouteHandler associated with the RouteHandler property of the Route object. In an ASP.NET MVC application, this is generally an instance of System.Web.Mvc.MvcRouteHandler which implements the IRouteHandler. When I have set the MvcRouteHandler to be my default Route Handler? Well, if you refer to the Figure 1.3, you will notice the System.Web.Mvc.RouteCollectionExtensions.MapRoute() extension method is used to map the default route in the public static method, RegisterRoutes(). When MapRoute() is used, the MvcRouteHandler is used by default to handle the routes.
 
IRouteHandler interface requires the route handler to implement the GetHttpHandler() method which returns an object that implements the System.Web.IHttpHandler interface. So, the MvcRouteHandler will return an object of System.Web.Mvc.MvcHandler through its GetHttpHandler() method with the current System.Web.Routing.RequestContext which encapsulates information about an HTTP request that matches a defined route. The RequestContext contains two properties; HttpContext of type System.Web.HttpContextBase and RouteData of type System.Web.Routing.RouteData. HttpContextBase is an abstract base class for the System.Web.HttpContextWrapper that wraps the System.Web.HttpContext to provide testability. It contains all the HTTP values sent by the web browser during a web request. The RouteData is where all the data concerning about the route and the segments are stored. First, it has the Route property which is of type System.Web.Routing.RouteBase that represents the route that was picked for a particular request by the System.Web.Routing.UrlRoutingModule at step a). The Values collection property will contain a collection URL parameter values and the default values for the route. In our example, based on the default route we have in the Global.asax, “{controller}/ {action}/ {id}” has controller, action and id segments. So for the URL, http://localhost/Customer/Edit/2, the Values collection property will have value for each segment defined in the route as follow:
 
 
Values[“controller”] == “Customer”


Values[“action”] == “Edit”


Values[“id”] == “2”


If you don’t want the default behavior implemented in System.Web.Mvc.MvcRouteHandler, then you can implement your own by inherits your custom route handler from the IRouteHandler interface and register it with the Routes property of the System.Web.Routing.RouteTable in the Application_Start event in the Global.asax file as shown in Figure 1.3. There is a simple sample implementation by Luis Abreu here.


c) In the previous step, the MvcRouteHandler return an object of System.Web.Mvc.MvcHandler and delegate control to it. The MvcHandler object will use the RequestContext object to identify an instance of System.Web.Mvc.IControllerFactory, generally the System.Web.Mvc.DefaultControllerFactory which is the controller factory that is used by default to create the controller that will handle the URL request. In this case, it is the CustomerController object. The DefaultControllerFactory will search through all the assemblies in the application domain for all classes that implement the System.Web.Mvc.IController interface and whose names end with the “Controller”. So, it can return any instance of IController interface regardless of the namespace or assembly it resides in.

The CustomerController inherits from the System.Web.Mvc.Controller abstract class which generally encapsulates all the basic functionalities that the ASP.NET MVC controller must have. The System.Web.Mvc.Controller which in turn inherits from the System.Web.Mvc.ControllerBase abstract class and ControllerBase implements the IController interface.

In fact, the MvcHandler doesn’t create the controller directly. It relies on the System.Web.Mvc.ControllerBuilder to return a reference to an instance of type System.Web.Mvc.IControllerFactory. Let look at the ControllerBuilder’s member as below:



Figure 1.5 System.Web.Mvc.ControllerBuilder’s Members


The ControllerBuilder has a public static Current property which returns a reference to the current ControllerBuilder instance. We can use this reference to access the instance method, GetControllerFactory() to return the actual concrete instance of the System.Web.Mvc.IControllerFactory.


ControllerBuilder controllerBuilder = ControllerBuilder.Current;

IControllerFactory controllerFactory = controllerBuilder.GetControllerFactory();


In this case, the actual concrete instance of IControllerFactory returned from the GetControllerFactory() method is DefaultControllerFactory which has been mentioned before.

As you can see, the ControllerBuilder provide an extensibility point where you can write your own custom controller factory and pass it to the ControllerBuilder through its SetControllerFactory() method in the Application_Start event in the Global.asax file. Once you have done this, the GetControllerFactory() will return your custom factory instance when it is called by MvcHandler within its ProcessRequest() method.

You can develop your own custom factory and employ any dependency injection framework to create and return the controller instance within the controller factory. The custom controller factory itself must implement the IControllerFactory interface. There is open source project on Codeplex called MVCContrib includes few controller factory classes to support various dependency injection container such as the StructureMap, Unity and etc.

There is a short article “Custom Controller Factory in ASP.NET MVC” by Keyvan Nayyeri which demonstrate how to write your own custom controller factory in the simplest form without using any dependency injection framework. This article provides you a quick reference on how to implement the custom controller factory.


d) After getting the controller from the IControllerFactory, the System.Web.Mvc.MvcHandler will call the controller’s Initialize() method to initialize properties on the controller. Then the MvcHandler will call the controller’s Execute() method to execute the specified request context. MvcHandler will wait for the controller to finish it work before clean up.

In fact, the Execute() method doesn’t carry out the execution itself. Instead it passes the control to the object that implements System.Web.Mvc.IActionInvoker to finish the works. For the controller that inherits from the System.Web.Mvc.Controller, the controller will grab it from the System.Web.Mvc.Controller.ActionInvoker property and pass the request to it. The default implementation of IActionInvoker in ASP.NET MVC framework is System.Web.Mvc.ControllerActionInvoker. So, it is actually the ControllerActionInvoker that executes and processes the request to return the result. Figure 1.6 shows some of the Controller’s member which includes the ActionInvoker property and the filters interfaces it implements (we will come to this later). You will be wondering how the instance of the IActionInvoker (ControllerActionInvoker) executes the various methods and filters on the controller itself. If you look at the IActionInvoker interface definition as follow

public interface IActionInvoker
{

     bool InvokeAction (ControllerContext controllerContext, string actionName);

}

When the controller invokes the action on the action invoker, the System.Web.Mvc.ControllerContext object and the action name are passed to it. The ControllerContext among other things is made up of the RequestContext and the Controller properties which enable the action invoker to call up your controller methods and filters.



Figure 1.6 System.Web.Mvc.Controller’s Properties and Filters Interfaces It Implements
 
 
As you can see, the separation of concern provides an extensibility point here. If you want the action invoker to do things differently from the ControllerActionInvoker, then you can implement your own invoker by inheriting from IActionInvoker and assign it to the controller’s ActionInvoker property. The ControllerActionInvoker encapsulates most of the execution logic and influences how the parameter are mapped to the action method’s parameters, the way the action method is chosen, the way the filters are chosen and executed. If you want to change the logic on these, then you need to extend the ControllerActionInvoker and override the necessary methods to accomplish your objective. Other reason that may require you to extend the ControllerActionInvoker is like incorporating the dependency injection to inject the dependency/services required by the filters in the ControllerActionInvoker. Whatever is the reason, the whole ASP.NET MVC execution pipeline is designed to be extensible and it is up to us to extend the framework to accomplish our task at hand whenever we see fit.

Well, things are getting much more interesting in the ControllerActionInvoker after it has taken over the control from the controller.

Firstly, the ControllerActionInvoker will locate and obtain the parameters values for the parameters on the action method. This job is done by the model binder which is responsible to convert the http request which carries the data in the form of form or querystring parameters into the strongly typed objects that can be consumed by the application. Let consider the following Create() action method on the CustomerController and Customer domain entity.
 
 
public class Customer
{
    public string CustomerID { get; set; }

    public string CompanyName { get; set; }
 
    public string ContactName { get; set; }

}


[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Customer customer)
{
   // TODO: Add insert logic here
}


What the model binder does is to convert the POST Form values which is merely a set of string key-value pairs like CustomerId=”2”, Company=”Test” and ContactName =”Test” into a new Customer instance before passing it to the Create() action method as parameter. This will save us a lot of work from just populating the properties of the entity object by reading the values from the System.Web.HttRequest.Form which return a collection of form variables. Without the model binder, then we need to write the following codes in the Create() action method which is not fun to work with if we have whole bunch of properties for the domain entity object. As you can see the model binder allows the controller to remain clean and run away from the responsibility to interrogate the HTTP request for the information it needs for the action method to carry out its task.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Customer customer)
{
    Customer customer = new Customer();

    customer.CustomerID = Request.Form(“CustomerID”);

    customer.CustomerID = Request.Form(“CompanyName”);

    customer.CustomerID = Request.Form(“ContactName”);

  // TODO: Add insert logic here

}

The model binder implements the System.Web.Mvc.IModelBinder interface. The default model binder comes with the ASP.NET MVC framework is System.Web.Mvc.DefaultModelBinder if we don’t specify any model binder to use. The model binder in ASP.NET MVC provides one more extensibility point. DefaultModelBinder provided by the ASP.NET MVC is able to translate the HTTP request information into complex models, including the nested types and arrays. However, if these behaviors don’t meet your need for the task at hand, then you can build your custom model binder by implementing the IModelBinder interface.

public interface IModelBinder
{
 
    object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);

}

There is an article here by Michael Valenty that demonstrates how to implement a simple custom model binder to read the HTTP submitted roles values and convert it into user roles collection.

Secondly, it will get a list of filter attributes that have been applied to the current action method and also to the type (controller). What is filter? Filter is generally an interceptor used to change the normal processing of an execution. It is a software design pattern used commonly in AOP (Attribute Oriented Programming). One of the use of AOP is it allows us to apply cross cutting concern like logging, authorization, authentication, caching and etc. Most of these concerns actually affect the entire application that spans multiple layers and tiers. So, it is better for them to be centralized in one code location and applying them as necessary to the code that requires their services. Code centralization avoids code duplication and allows code to be changed in one place so inconsistency of code update is prevented. In ASP.NET MVC, filters are interceptor methods that can execute before and after the action method execution. Applying filters are very simple in ASP.NET MVC application because they are implemented as attributes which you can easily decorate them to the action method or the entire controller. Filter attributes in ASP.NET MVC extend the System.Web.Mvc.FilterAttribute and implements one of more of the following filters:
 
o Authorization Filter - Implements System.Web.Mvc.IAuthorizationFilter interface.

o Action Filter – Implements System.Web.Mvc.IActionFilter interface.

o Result Filter - Implements System.Web.Mvc.IResultFilter interface.

o Exception Filter – Implements System.Web.Mvc.IExceptionFilter interface


If you observe the order of the above filters, they are always executed in the order shown. Authorization filter is always executed first before any other type of filters. If the authorization fails at this stage, then the rest of the filters will be skipped and the action method won’t be executed. Only if the authorization filter passes, then the execution of action filters will be attempted. Action filter as it name implies, allows you to include additional logic to be executed before and after a controller’s action method executes. Result filter as it name implies, allow you to include additional logic to execute before and after the view result is executed. Exception filter is the last type of filter to execute. It is used to handle the errors raised by either the controller action or the controller result. Anywhere, the exception filter only execute in the event error is raised during the action or result execution. Otherwise, it won’t run at all. The exception filter offer us a way to handle the before it is thrown up further to the Global.asax.

Example of authorization filter attribute is System.Web.Mvc.AuthorizeAttribute which restricts access to the action method based on a particular user or role. AuthorizeAttribute implements IAuthorizationFilter interface which has only one method signature which must be implemented by the implementer.

public interface IAuthorizationFilter
{
  
    void OnAuthorization(AuthorizationContext filterContext);

}

The System.Web.Mvc.AuthorizationContext is passed to the OnAuthorization method. By overriding this method, you can customize the authorization to your application needs. For e.g. authorize the user against the access rights stored in the custom store. As the AuthroizationContext inherits from the System.Web.Mvc.ControllerContext , you can access to the HttpContext wrapped in the HttpContextBase, RequestContext, Controller, RouteData and etc. There is a very simple sample here that creates a new authorize filter attribute by inheriting from the existing AuthorizeAttribute . The code in the sample allows you to assign the roles to the MultipleEnumRolesAuthorizeAttribute using enumeration instead of the string value.

System.Web.Mvc.ActionFilterAttribute form the base class for all the action filter attributes. This class implements the System.Web.Mvc.IActionFilter and System.Web.Mvc.IResultFilter interfaces and derive from the System.Web.Mvc.FilterAttribute. It comes in handy if you need to implement your own custom action filter attribute; you can simply derive your custom action filter attribute from this class. There are two action filter attributes that comes with the ASP.NET MVC framework; System.Web.Mvc.OutputCacheAttribute and System.Web.Mvc.AsyncTimeoutAttribute

The IActionFilter has two signature methods as follow:

public interface IActionFilter
{

    void OnActionExecuted(ActionExecutedContext filterContext);

    void OnActionExecuting(ActionExecutingContext filterContext);

}


OnActionExecuted method is called after the controller action method is executed and the OnActionExecuting method is called before the controller action method is executed.


The IResultFilter has two signature methods as follow:

public interface IResultFilter
{

    void OnResultExecuted(ResultExecutedContext filterContext);

    void OnResultExecuting(ResultExecutingContext filterContext);

}

OnResultExecuted method is called after the controller action result is executed and the OnResultExecuting method is called before the controller action result is executed.

The term used to refer to the action filter is not particularly clear as it implement both the action and result filter. Anyway, any type of filters in ASP.NET MVC is referred to as action filters generally.

As mentioned earlier, only if the authorization filters pass, then the execution come to the action filters. The OnActionExecuting method on the action filters is the first to execute. Notice that the System.Web.Mvc.ActionExecutingContext instance is passed to this method. To stop execution of any further action filters and the action method itself, you can set the Result property of ActionExecutingContext to any derived class of System.Web.Mvc.ActionResult that you prefer.

Then the execution will comes to the action method on the controller. The parameters on the action method are supplied by the model binder.

Once the action method is executed, the OnActionExecuted method is executed on the action filters. Notice that the System.Web.Mvc.ActionExecutedContext instance is passed to this method. You have the chance to get the exception that is thrown during the execution of the action method from the Exception property of the ActionExecutedContext instance if any. To handle the exception and stop the exception from propagating further, you can set the ExceptionHandled property of ActionExecutedContext instance to true.

Result filters will be executed after the action filters have run. Again, execution will only come to this stage if there is no unhandled exception in the controller’s action method and IActionFilter.OnActionExecuted. As mentioned earlier, the exception thrown in the action method can be handled in the IActionFilter.OnActionExecuted method to stop it from further propagating. Exception thrown in the result execution can also be handled in the IResultFilter.OnResultExecuted to stop it from further propagating by setting the ResultExecutedContext.ExceptionHandled property to true. The exception that is thrown during the result execution can also be retrieved from the ResultExecutedContext.Exception property.

Exception filters if any will only be executed if there is unhandled exception in the action and result execution. If the exception is handled in the IActionFilter.OnActionExecuted or IResultFilter.OnResultExecuted method, then the exception filters won’t be executed. System.Web.Mvc.HandleErrorAttribute is the exception filter attribute comes with the ASP.NET MVC framework to handle exception that is thrown by an action method. This attribute implements the System.Web.Mvc.IExceptionFilter interface as follow. The OnException method is called when there is unhandled exception in the action method being decorated with the HandleErrorAttribute.

public interface IExceptionFilter
{

    void OnException(ExceptionContext filterContext);

}

At last, System.Web.Mvc.ActionResult object will be produced on the successful execution of a controller action. ActionResult is an abstract class which encapsulates the result of an action method. The object produced normally derives from ActionResult. In ASP.NET MVC framework, there are System.Web.Mvc.ViewResult (for html output), System.Web.Mvc.JsonResult (for Json output), System.Web.Mvc.ContentResult (string only output in http response) and etc. For a complete list of the ActionResult derived type, you can refer to the Figure 10 of the MSDN article “The Life And Times of an ASP.NET MVC Controller

ActionResult provides another extensibility point where you can create your custom ActionResult implementation. Phil Haack has written a custom file download action result for ASP.NET MVC here.


Finally, in ASP.NET MVC, there is a view engine which is responsible to render the view to the response. In ASP.NET MVC, we have the System.Web.Mvc.WebFormViewEngine which processes .aspx based views. WebFormViewEngine implements System.Web.Mvc.IViewEngine interface which defines a method required of a view engine. This also provides another extensibility point where you can write your custom view engine and register it with the System.Web.Mvc.ViewEngines in the Application_Start event in the Global.asax file. Anywhere, there has been a number of open source view engines made available for ASP.NET MVC such as the Spark, Brail, NHaml and etc in the MVCContrib open source project. There are ported from other technologies.


Time to end my post. I have found another diagram on the web which depicts the ASP.NET MVC flow in much more details as compred to the Figure 1.2. I would like to include here and give the author; Justin Etheredge a credit for drawing out the diagram. If you are interested in his post that comes with the diagram, please follow here.





See you in my next post.
Bye & stay tune...



Some Other Recommended Readings


ASP.NET MVC -> http://www.asp.net/mvc/

ScottGu's Blog -> http://weblogs.asp.net/scottgu/