In Global.asax.cs we register routes something like this
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Employee", action = "CreateEmployee", id = UrlParameter.Optional } // Parameter defaults
);
}
routes.MapRoute is extension method defined in System.Web.Mvc.RouteCollectionExtensions.cs. When you decompile this you will notice that how a route with particular URL is being register and associated with MvcRouteHandler.
Route route = new Route(url, new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
There are bunch of default HttpModules and HttpHandlers in your IIS configuration. Just take a look here - %WINDOWS%\Microsoft.NET\Framework\v4.0.30319\Config\web.config.
and in the list of modules (
) notice UrlRoutingModule
Now decompile UrlRoutingModule and look at PostResolveRequestCache where it Matches the HTTP request to a route, retrieves the handler for that route, and sets the handler as the HTTP handler for the current request.
public virtual void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = this.RouteCollection.GetRouteData(context);
if (routeData == null)
{
return;
}
IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
}
if (routeHandler is StopRoutingHandler)
{
return;
}
RequestContext requestContext = new RequestContext(context, routeData);
context.Request.RequestContext = requestContext;
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[]
{
routeHandler.GetType()
}));
}
if (!(httpHandler is UrlAuthFailureHandler))
{
context.RemapHandler(httpHandler);
return;
}
if (FormsAuthenticationModule.FormsAuthRequired)
{
UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
return;
}
throw new HttpException(401, SR.GetString("Assess_Denied_Description3"));
}
This is how MvcRouteHandler(routeHandler.GetHttpHandler(requestContext)) is used for the Mvc application. In case of aspx.net, all the handlers are listed in the web.config file, which are based on the file extension. You will noticed that there is non for mvc.
As requests move through the pipeline(modules) it find UrlRouting module (refer to web config). UrlRouting module matches incoming request URL with registered collections of Routes. For found matched Route it gets corresponding route handler (MvcRouteHandler). From routehandler (MvcRouteHandler) it gets the GetHttpHandler which in this case if MvcHandler.
Once the request comes to the MvcHandler.ProcessRequest, it creates controller from the controller factory (DefaultControllerFactory) and then call execute method on the controller which calls controller action.
Execute (member of IController which is implemented in ControllerBase)
-> ExecuteCore (which is implemented in Controller)
->ControllerActionInvoker.InvokeAction
->GetParameterValues- This uses model binder to get the parameter value.
-> Based on filter it calls filter.OnActionExecuting and finally call controller action.
At this point in the lifecycle, we’ve entered our application code. Your controller action return ActionResult.
->After view is executed it calls filter.OnActionExecuted
->ControllerActionInvoker.InvokeActionResult
->ViewResultBase->ExecuteResult
->FindView (which is implementation of IViewEngine). This returns ViewEngineResult which is an implementation of IView
->This then call Render(member of IView) on the View and pass ViewData,tempdata and context.HttpContext.Response.Output writer so that View can process the data and write it to the output.
1. RouteConstraint
The URL Routing framework recognizes two different types of constraints. If you supply string for a constraint then the string is interpreted as a regular expression. The other option is to create a custom constraint by creating an instance of a class that implements the IRouteConstraint interface. Routing framework provides HttpMethodConstraint.
2. RouteHandler
3. ControllerFactory
Mvc handler gets the name of controller (Based on the route) and then uses controller factory (DefaultControllerFactory) to create an instance of controller. The default factory uses reflection to create an instance that implements IController and whose name ends with Controller.
DefaultControllerFactory uses the parameter-less constructor so if you want to use DI it will throw error stating that “No parameterless constructor is defined for this object”. This is one of the case where you can implement a custome controller factory by implementing DefaultControllerFactory and override GetControllerInstance.
4. ActionInvoker- This is the sequence of operation which happens here.
ControllerActionInvoker.InvokeAction
InvokeAuthorizationFilters
GetParameterValues
InvokeActionMethodWithFilters
OnActionExecuting
InvokeActionMethod Returns ActionResult
OnActionExecuted
InvokeActionResultWithFilters
OnResultExecuting
InvokeActionResult Calls ExecuteResult on ActionResult returned by InvokeActionMethod
OnResultExecuted
5. ActionMethodSelectorAttribute
Actions, with the default action invoker, are selected based on their name.
One of the scenario for a custom selector attribute is if you want to choose action based on the browser like mobile browser or desktop browser.
6. AuthorizationFilter
7. ActionFilter
Action Filters are executed before and after an action is executed.
Filters can be used for many purpose like to extract data from session\httpcontext. This makes controller lighter and any component called from controller free from objects like session data\httpcontext. Having this encapsulated in filter makes it easily reusable across different controller action. The other places where I have used is to manage (set/get) http headers ( like If-Modified-Since and If-None-Match) specifically for Etag to support conditional caching. In short I consider this to be a place for anything which doesnot belongs to model.
8. ModelBinder
The default model binder maps HTTP parameters (by using
value providers) to action method parameters using their names.
For DefaultModelBinder you need to have parameter object with parameterless constructor. Also you cannot use interface type as a parameter. To extend the support for these types of parameter you can extend DefaultModelBinder. Also the other condition you might use it to convert the id of the person directly to the Person object looking up on the database, although I consider this kind of thing to belong to model.
9. ValueProvider
Value providers are used by the model binding system in MVC to populate the values of model objects. MVC 3.0 includes value providers for several common value sources
System.Web.Mvc.FormValueProviderFactory
System.Web.Mvc.HttpFileCollectionValueProviderFactory
System.Web.Mvc.QueryStringValueProviderFactory
System.Web.Mvc.RouteDataValueProviderFactory
For any other value provider like CookieValueProviderFactory we can implement ValueProviderFactory.
10. ControllerBase
All controllers inherit from the base class Controller. To encapsulate common logic or conventions you can have your own base calss which inherits from Controllers. You can also apply filter to this base.
11. ResultFilter
Like action filter result filters are executed before and after action result is executed. ActionFilterAttribute implements both IActionFilter, IResultFilter.
Logging/Output caching from action result can be done at this level.
12. ActionResult
ASP.NET MVC comes with many different kind of results to render views, to render JSON, plain text, files and to redirect to other actions.
You can implement this in case of any specific type of requirement. One of the example where I have tried this is to write Xsl Transformation ActionResult where I pass xml object (same as view model) and based on the action it uses xsl file to transform xml object to output page.
13. ViewEngine
Example Razor(cshtml) and ASPX/WebForm view
One of the example where I create a MobileCapableRazorViewEngine by deriving it from RazorViewEngine and overriding FindView to specify view name based on the browser from where the request is coming.
14. HtmlHelper
HtmlHelper is just an extension method of the HtmlHelper class.Views must be very dumb and thin, and they should only have html markup and calls to HtmlHelpers. Writting helpers come very handy for extracting the code from the view and putting it into something that is testable\reusable.
15. TempDataProvider
Life span of TempData object is only till the subsequent request, or until the item is removed explicitly. This is useful when you want to pass data to another view that you will be redirecting to, rather than rendering to. By default, TempData is stored in the session using SessionStateTempDataProvider.
CustomeTempDataProvider just need to implement ITempDataProvider which has method SaveTempData where you can put your logic for storing this wherever you want.