<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.charteris.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>gopalk</title><link>http://blogs.charteris.com/blogs/gopalk/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007 SP2 (Build: 20611.960)</generator><item><title>ASP.NET MVC in production</title><link>http://blogs.charteris.com/blogs/gopalk/archive/2009/03/17/asp-net-mvc-in-production.aspx</link><pubDate>Tue, 17 Mar 2009 19:07:46 GMT</pubDate><guid isPermaLink="false">0cdfd867-77e4-483c-9e74-84c93cc8eba0:781</guid><dc:creator>gopalk</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.charteris.com/blogs/gopalk/rsscomments.aspx?PostID=781</wfw:commentRss><comments>http://blogs.charteris.com/blogs/gopalk/archive/2009/03/17/asp-net-mvc-in-production.aspx#comments</comments><description>&lt;h3&gt;Is ASP.NET MVC ready for production use? &lt;/h3&gt;  &lt;p&gt;ASP.NET MVC Beta version was the first one to come with an explicit go-live licence. We went live with our first ASP.NET MVC website in December, based on ASP.NET MVC Beta and the results have so far been very impressive. The beta was of high-quality and very stable during development. With the release candidates its only got better&amp;#160; and hopefully the release version isn’t too far away. In my opinion releasing the source code and keep the community involved via Codeplex, forums and blogs has played no small part in keeping the quality of this framework high.&lt;/p&gt;  &lt;p&gt;The website has performed very well since then under some pretty intense load. So in our case, ASP.NET MVC is certainly proved itself ready for production use. Here I have tried to compile a list of ASP.NET MVC tips, advantages and pain points based on my experience with ASP.NET MVC.&lt;/p&gt;  &lt;h3&gt;Tips for MVC&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Before using ASP.NET MVC think about your UI requirements. Are you counting on a third party UI library? If you are thinking of using third party controls that use postback or viewstate then ASP.NET MVC may not be for you! Although bear in mind that it is possible to have ASP.NET webforms page within an ASP.NET MVC web application. &lt;/li&gt;    &lt;li&gt;Decide on client side and server side validation strategy early : ASP.NET MVC doesn’t have validation built in, it only provides support for it via &lt;strong&gt;ModelState&lt;/strong&gt;. You’ll need to decide on a server side validation framework e.g. Enterprise validation block, data annotations, Castle Validator etc. You’ll also need to decide on a client side validation framework e.g. jQuery validate plugin. &lt;/li&gt;    &lt;li&gt;Understand controller lifecycle and ActionFilters: Understanding the lifecycle of the controllers and about ActionFilters will help you create controllers and presentation logic correctly and with minimal code. It will also help you move the cross cutting concerns like authentication, authorization etc out of your presentation logic. See my &lt;a href="http://blogs.charteris.com/blogs/gopalk/archive/2009/02/11/how-does-asp-net-mvc-work-part-2.aspx"&gt;previous post&lt;/a&gt; for this. &lt;/li&gt;    &lt;li&gt;Have base class hierarchy for controller and views to provide required functionality: Don’t derive from the Controller class directly for your controllers, but create a custom base controller where you can provide functionality common across all controllers. I have found this useful for Views and Model classes as well. &lt;/li&gt;    &lt;li&gt;Move routes out of code into configuration: Having to recompile every time you add a new route is a pain, move the routes out into a web.config or an external file. This is easy to do as ‘defaults’ parameter on &lt;strong&gt;RouteCollectionExtensions.MapRoute&lt;/strong&gt; no longer expects anonymous types, an object of type &lt;strong&gt;RouteValueDictionary&lt;/strong&gt; can be passed in. &lt;/li&gt;    &lt;li&gt;You can use URL rewrite module along with routing: It is possible to use regex url rewrite module along with MVC. This will kick in before MVC receives the request and MVC will receive the modified request. This is useful for cases where you want to use regular expressions as as regex routes are not currently supported by &lt;strong&gt;MvcRouteHandler&lt;/strong&gt;. &lt;/li&gt;    &lt;li&gt;Keep Views as dumb as possible: Remember Views are supposed to be so dumb as to require minimal testing, so keep it that way. &lt;/li&gt;    &lt;li&gt;Keep controller as lean as possible: Having too much code in the controller is a sign that you are perhaps missing a Service facade class. &lt;/li&gt;    &lt;li&gt;Anything involving viewstate or postback will not work within a ASP.NET MVC page: Support for ASP.NET webforms controls is limited e.g. ViewState and Postbacks aren’t supported. Test any controls you plan to use early on with ASP.NET MVC. There are other options like MVP if you absolutely need a server control not supported by MVC but want the testability benefits of ASP.NET MVC. ASP.NET webforms page can be used within an ASP.NET MVC web application. &lt;/li&gt;    &lt;li&gt;RouteData is very useful – If you want to get hold of any route related data associated with the current request. It is accessible within Controller and Views and it can be used to retrieve current action name, controller name, route name etc. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Why MVC?:&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Separation of concerns – separation of concerns in dividing the UI (View) from presentation logic (Controller). The domain model is separated from the above two as well, but that’s a common practice even if you are using ASP.NET MVC webforms. &lt;/li&gt;    &lt;li&gt;Testability –The controller receives user input, acts on user input, supplies ViewData to the View and presents the View to the user. This clear input and output model means that controllers are very testable. &lt;/li&gt;    &lt;li&gt;Extensible – Extensibility is a big feature of ASP.NET MVC. Some of the many extensibility hooks within ASP.NET MVC are:      &lt;ul&gt;       &lt;li&gt;RouteHandler – The default ASP.NET MVC route handler is &lt;strong&gt;MvcRouteHandler&lt;/strong&gt;. A custom route handler can be used if you want customized route handling logic for a particular route. &lt;/li&gt;        &lt;li&gt;ControllerFactory – Create your own controller factory if you want to instantiate your controller using an IoC container, or choose one from here http://www.codeplex.com/mvccontrib &lt;/li&gt;        &lt;li&gt;ViewEngines – Views are normally located and processed by WebForms ViewEngine infrastructure, but there are custom ViewEngines available like nVelocity etc. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Control over HTML – ASP.NET MVC allows fine grained control over the HTML generated, great if you don’t like all auto generated HTML related to viewstate and server controls in ASP.NET webforms. &lt;/li&gt;    &lt;li&gt;REST – ASP.NET MVC provides SEO friendly and RESTful URL’s &lt;/li&gt;    &lt;li&gt;MVCContrib – Last but not the least, a great resource, provides lots of community contributed content for MVC. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;That said ASP.NET MVC is still very new and naturally has a few areas that need a bit of work:&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Grouping of controllers – ASP.NET MVC doesn’t provide a way to group controllers into ‘areas’, which is quite important for a large project. There are a few solutions from the ASP.NET MVC community for this, including one here: http://blog.codeville.net/2008/11/05/app-areas-in-aspnet-mvc-take-2/ &lt;/li&gt;    &lt;li&gt;View and ViewData issues– ViewData container object is not strongly typed, this results in a lot of defensive coding within the View in reading values from this container. This also causes any possible type mismatches not to come to light until runtime. Using strongly typed views can help this issue to an extent, so can using Generics base ViewData setters and getters like this: &lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;   &lt;div style="border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;height:35px;background-color:#f4f4f4;"&gt;     &lt;div style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;       &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;SetViewData&amp;lt;T&amp;gt;(“keyname”, T data);&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;End to end validation framework – An end-to-end validation framework is missing. This at the moment means defining validation rules both at the server side (e.g. via Enterprise validation block) and client side (e.g. via jQuery) separately. The new xVal framework aims to address this issue: http://www.codeplex.com/xval &lt;/li&gt;

  &lt;li&gt;Repeater controls – Simple rendering controls with templating capability such as Repeaters etc are sorely missed in ASP.NET MVC. An possible solution here: http://haacked.com/archive/2008/05/03/code-based-repeater-for-asp.net-mvc.aspx &lt;/li&gt;

  &lt;li&gt;Self contained controls – At the moment user controls in ASP.NET MVC are not fully encapsulated i.e. the code required to load the ViewData for the control must be called from every controller that presents the control. Subcontrollers aim to address this: http://www.codeplex.com/mvccontrib &lt;/li&gt;

  &lt;li&gt;IIS6 install a bit messy – Installing MVC on IIS6 involves setting wildcard mapping and needs to carefully planned and tested early on. Make sure to disable wildcard mapping from any sub folder that only contain only static files for performance reasons. More info here: http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx &lt;/li&gt;

  &lt;li&gt;Regex support for the routes – At the moment routing system doesn’t support regex based routing. A possible solution here : http://blog.sb2.fr/post/2009/01/03/Regular-Expression-MapRoute-With-ASPNET-MVC.aspx &lt;/li&gt;

  &lt;li&gt;Asynchronous processing – While there is no out of the box support for asynchronous processing within ASP.NET MVC, here is a possible solution: http://blog.codeville.net/2008/04/05/improve-scalability-in-aspnet-mvc-using-asynchronous-requests/ &lt;/li&gt;

  &lt;li&gt;Dynamic loading of routing – Routes are right now added from within code and there is no support for storing routes within an external data store, although such a functionality can be easily added. Many possible solutions available for this including this: http://mnour.blogspot.com/2008/11/mvc-routing-using-custom-configuration.html &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given the ASP.NET MVC framework is relatively new, these shortcomings are quite understandable. Furthermore most of the above issues also have community contributed solutions and workaround, so none of them pose a major impediment to the use of ASP.NET MVC. The framework should also improve and add features that are currently missing with newer releases. It remains to be seen how the vast server controls market for ASP.NET webforms responds to ASP.NET MVC. I think that this will be quite important for the widespread adoption of ASP.NET MVC.&amp;#160; Overall, in my opinion, ASP.NET MVC provides us with a new reliable, testable and extensible framework for web development which is well worth trying out.&lt;/p&gt;
&lt;div id="SocialBookmarks"&gt;&lt;a href="http://del.icio.us/post?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f03%2f17%2fasp-net-mvc-in-production.aspx&amp;tags=&amp;title=ASP.NET+MVC+in+production" mce_href="http://del.icio.us/post?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f03%2f17%2fasp-net-mvc-in-production.aspx&amp;tags=&amp;title=ASP.NET+MVC+in+production"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/delicious.gif"&gt;Del.icio.us&amp;nbsp;&lt;/a&gt;&lt;a href="http://digg.com/submit?phase=2&amp;url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f03%2f17%2fasp-net-mvc-in-production.aspx&amp;title=ASP.NET+MVC+in+production&amp;tags=" mce_href="http://digg.com/submit?phase=2&amp;url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f03%2f17%2fasp-net-mvc-in-production.aspx&amp;title=ASP.NET+MVC+in+production&amp;tags="&gt;&lt;img border="0" src="/Themes/leanandgreen/images/digg.gif"&gt;Digg It&amp;nbsp;&lt;/a&gt;&lt;a href="http://www.facebook.com/share.php?u=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f03%2f17%2fasp-net-mvc-in-production.aspx" mce_href="http://www.facebook.com/share.php?u=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f03%2f17%2fasp-net-mvc-in-production.aspx"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/facebook.gif"&gt;Share on Facebook&amp;nbsp;&lt;/a&gt;&lt;a href="http://www.stumbleupon.com/submit?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f03%2f17%2fasp-net-mvc-in-production.aspx&amp;title=ASP.NET+MVC+in+production" mce_href="http://www.stumbleupon.com/submit?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f03%2f17%2fasp-net-mvc-in-production.aspx&amp;title=ASP.NET+MVC+in+production"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/stumble.gif"&gt;Stumble It!&lt;/a&gt;&lt;/div&gt;&lt;img src="http://blogs.charteris.com/aggbug.aspx?PostID=781" width="1" height="1"&gt;</description></item><item><title>How does ASP.NET MVC work – Part 2</title><link>http://blogs.charteris.com/blogs/gopalk/archive/2009/02/11/how-does-asp-net-mvc-work-part-2.aspx</link><pubDate>Wed, 11 Feb 2009 07:41:21 GMT</pubDate><guid isPermaLink="false">0cdfd867-77e4-483c-9e74-84c93cc8eba0:770</guid><dc:creator>gopalk</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.charteris.com/blogs/gopalk/rsscomments.aspx?PostID=770</wfw:commentRss><comments>http://blogs.charteris.com/blogs/gopalk/archive/2009/02/11/how-does-asp-net-mvc-work-part-2.aspx#comments</comments><description>&lt;p&gt;In the &lt;a href="http://blogs.charteris.com/blogs/gopalk/archive/2009/01/20/how-does-asp-net-mvc-work.aspx"&gt;last post&lt;/a&gt; we saw how an ASP.NET MVC request gets routed through to the MVC framework through the ASP.NET framework. We also saw that the &lt;b&gt;MvcHandler&lt;/b&gt; class is the HttpHandler responsible for servicing an ASP.NET MVC-request. A simplistic view of the order in which routing and MVC classes come into play is like this:&lt;/p&gt;  &lt;p&gt;&lt;b&gt;UrlRoutingModule&lt;/b&gt; -&amp;gt; &lt;b&gt;MvcRoutingHandler&lt;/b&gt; -&amp;gt; &lt;b&gt;MvcHandler&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;So at this stage our request has got an HttpHandler assigned in the form of &lt;b&gt;MvcHandler&lt;/b&gt;. Moving ahead in the &lt;b&gt;HttpApplication&lt;/b&gt; event processing, the fulfilling of a request takes place when the &lt;b&gt;ProcessRequest&lt;/b&gt; method on the &lt;b&gt;MvcHandler &lt;/b&gt;gets invoked. &lt;/p&gt;  &lt;p&gt;&lt;b&gt;MvcHandler&lt;/b&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Within the &lt;b&gt;ProcessRequest&lt;/b&gt; method, the original &lt;b&gt;HttpContext&lt;/b&gt; is wrapped into an &lt;b&gt;HttpContextWrapper&lt;/b&gt; instance. &lt;b&gt;HttpContextWrapper&lt;/b&gt; implements an abstract class called &lt;b&gt;HttpContextBase&lt;/b&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;u&gt;Loose coupling&lt;/u&gt;: Within an ASP.NET MVC controller, &lt;b&gt;HttpContext&lt;/b&gt; is referenced not directly but via this abstract &lt;b&gt;HttpContextBase&lt;/b&gt; class. As evident, this enables loose coupling between your controller class and the &lt;b&gt;HttpContextWrapper&lt;/b&gt; instance and thus improves testability by allowing you to easily mock your &lt;b&gt;HttpContextBase&lt;/b&gt; class when performing unit tests. This loose coupling also extends to other objects like Request (referenced to via &lt;b&gt;HttpRequestBase&lt;/b&gt;) and Response (&lt;b&gt;HttpResponseBase&lt;/b&gt;). These abstract types are defined within a separate assembly &lt;i&gt;System.Web.Abstractions.dll&lt;/i&gt;. This opens up the possibility of using them outside the MVC framework! &lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;Compare this to a traditional WebForms Page, where the Page class references the &lt;b&gt;HttpContext&lt;/b&gt; via a direct reference, and the &lt;b&gt;HttpContext&lt;/b&gt; object is also sealed. So it’s difficult to mock &lt;b&gt;HttpContext&lt;/b&gt; for testing purposes, thus making a WebForm page difficult to test. This is one clear advantage of ASP.NET MVC over traditional WebForms.&lt;/p&gt; &lt;/blockquote&gt;  &lt;ul&gt;   &lt;li&gt;At this point we have two classes that carry information about the request. These are &lt;b&gt;RouteData&lt;/b&gt; and &lt;b&gt;HttpContextWrapper &lt;/b&gt;(Packaged up into &lt;b&gt;RequestContext&lt;/b&gt; and assigned to &lt;b&gt;MvcHandler&lt;/b&gt; earlier during the &lt;b&gt;PostResolveRequest&lt;/b&gt; stage of the &lt;b&gt;UrlRoutingModule&lt;/b&gt;). &lt;b&gt;RouteData&lt;/b&gt; is a dictionary object containing key value pairs related to the matching route. The information &lt;b&gt;RouteData&lt;/b&gt; will contain will typically be controller name, action name, route name, default parameter etc matching the current request. These are extracted from the parameters passed into the &lt;b&gt;RouteCollection.RegisterRoute&lt;/b&gt; calls made in Global.asax:       &lt;div style="border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:93.36%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;height:84px;background-color:#f4f4f4;"&gt;       &lt;div style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:94.39%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;height:93px;background-color:#f4f4f4;border-bottom-style:none;"&gt;         &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   1:&lt;/span&gt; routes.MapRoute(&lt;/pre&gt;

        &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   2:&lt;/span&gt;     &lt;span style="color:#006080;"&gt;&amp;quot;Default&amp;quot;&lt;/span&gt;, &lt;span style="color:#008000;"&gt;// Route name &lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   3:&lt;/span&gt;     &lt;span style="color:#006080;"&gt;&amp;quot;{controller}/{action}/{id}&amp;quot;&lt;/span&gt;, &lt;span style="color:#008000;"&gt;// URL with parameters &lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   4:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; { controller = &lt;span style="color:#006080;"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;, action = &lt;span style="color:#006080;"&gt;&amp;quot;Index&amp;quot;&lt;/span&gt;, id = 1 } &lt;span style="color:#008000;"&gt;// Parameter defaults&lt;/span&gt;&lt;/pre&gt;

        &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   5:&lt;/span&gt; );&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;b&gt;RouteData&lt;/b&gt; can also be used from within the Controller (via &lt;b&gt;ControllerContext&lt;/b&gt;) and View (via &lt;b&gt;ViewContext&lt;/b&gt;) to get the current route name, action name, controller name etc. Thanks to &lt;b&gt;RouteData&lt;/b&gt; dictionary, at this point MVC knows the name of the controller and the action to be invoked.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;b&gt;ControllerFactory (DefaultControllerFactory)&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Further in the &lt;b&gt;ProcessRequest&lt;/b&gt; method, a controller must be located to fulfil the current request. To do this, a controller factory is acquired first. By default in ASP.NET MVC this is an instance of &lt;b&gt;DefaultControllerFactory.&lt;/b&gt; In typical ASP.NET MVC fashion there is an extensibility point here too. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;A controller factory must implement &lt;b&gt;IControllerFactory&lt;/b&gt; interface and a custom controller factory can be registered to override the &lt;b&gt;DefaultControllerFactory&lt;/b&gt; in Global.asax. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;div style="border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;"&gt;
    &lt;div style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;
      &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Application_Start() {&lt;/pre&gt;

      &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   2:&lt;/span&gt;     ControllerBuilder.Current.SetControllerFactory(&amp;lt;Your controller factory&amp;gt;);&lt;/pre&gt;

      &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   3:&lt;/span&gt;     ...           &lt;/pre&gt;

      &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   4:&lt;/span&gt; }&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;p&gt;One of the reasons you would want to register a custom controller factory is, if you want your controllers to be instantiated by an &lt;b&gt;IoC (Inversion of Control)&lt;/b&gt; container and injected with dependencies like Loggers etc dynamically. There is some more information on how to create a custom controller factory for ASP.NET MVC here: &lt;a href="http://www.pnpguidance.net/Post/SetDefaultControllerFactoryIControllerFactoryASPNETMVCFramework.aspx"&gt;http://www.pnpguidance.net/Post/SetDefaultControllerFactoryIControllerFactoryASPNETMVCFramework.aspx&lt;/a&gt;&amp;#160;&lt;/p&gt;

  &lt;p&gt;The MVCContrib project on Codeplex makes available controller factory classes with support for various popular &lt;b&gt;IoC&lt;/b&gt; frameworks like StructureMap, Castle Windsor, Unity Framework and Spring.NET: &lt;a href="http://www.codeplex.com/MVCContrib"&gt;http://www.codeplex.com/MVCContrib&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;b&gt;IController (Controller)&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Once an instance of the controller is retrieved from the controller factory, &lt;b&gt;Initialize&lt;/b&gt; method is called on the controller. This is an important part of the controller lifecycle which provides access to the request and is a good place to initialize properties on the controller. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;b&gt;IActionInvoker (ControllerActionInvoker)&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Next the &lt;b&gt;Execute&lt;/b&gt; method is invoked on the instance of Controller class and &lt;b&gt;RequestContext&lt;/b&gt; is passed in as an argument. This sets off the controller lifecycle. An object of type &lt;b&gt;IActionInvoker&lt;/b&gt; rather than the controller itself controls the order in which various methods on the controller and filters are executed. 

    &lt;div style="border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;height:47px;background-color:#f4f4f4;"&gt;
      &lt;div style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;
        &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; IActionInvoker.InvokeAction(ControllerContext controllerContext, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; actionName)&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;i&gt;(ControllerContext is composed of the RequestContext and Controller instance.)&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Notice the separation of concerns and yet another point for extension. A custom implementation of &lt;b&gt;IActionInvoker&lt;/b&gt; can be assigned to the &lt;b&gt;Controller&lt;/b&gt; if we want our action invoker to do things a bit differently. The default implementation of &lt;b&gt;IActionInvoker&lt;/b&gt; is &lt;b&gt;ControllerActionInvoker &lt;/b&gt;class, and does quite a bit behind the scenes as we’ll see below: &lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;ul&gt;
    &lt;li&gt;First parameter values are obtained for the parameters on the action method. This is done by a &lt;b&gt;ModelBinder&lt;/b&gt;. A &lt;b&gt;ModelBinder&lt;/b&gt; is responsible for converting the data in request (i.e. form parameters, querystring parameters etc) into parameter values that an action method accepts. Of course, this is yet another extensibility point in the framework where a custom &lt;b&gt;ModelBinder&lt;/b&gt; can be assigned to an action method via the use of attributes (Note the influence of &lt;b&gt;AOP &lt;/b&gt;(aspect oriented programming) in the framework). The default &lt;b&gt;ModelBinder&lt;/b&gt; is used if a custom ModelBinder is not specified. More information here on creating custom ModelBinders: &lt;a href="http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx"&gt;http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx&lt;/a&gt; &lt;/li&gt;
  &lt;/ul&gt;

  &lt;ul&gt;
    &lt;li&gt;Now the various filters are executed. Simply put, filters are interceptor methods that can execute before and after the action method execution. They allow you to separate cross cutting concerns or non-action-specific code from the code in the action method (Notice the nice use of &lt;b&gt;AOP&lt;/b&gt;). There are different types of filters: &lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;ol&gt;
    &lt;ol&gt;
      &lt;li&gt;Authorization Filter – IAuthorizationFilter interface &lt;/li&gt;

      &lt;li&gt;Action Filter – IActionFilter interface &lt;/li&gt;

      &lt;li&gt;Result Filter – IResultFilter interface &lt;/li&gt;

      &lt;li&gt;Exception Filter – IExceptionFilter interface &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/ol&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;u&gt;Authorization Filter&lt;/u&gt;&lt;b&gt; &lt;/b&gt;is the first set of filters to be executed. Processing can be halted within this stage by cancelling the action. This can be done by setting the cancel property on &lt;b&gt;AuthorizationContext&lt;/b&gt; to true.In the code below, the further processing of the action is cancelled, the &lt;b&gt;RedirectResult&lt;/b&gt; is executed which should result in a redirect to Login action. An authorization attribute can be implemented by deriving from &lt;b&gt;AuthorizeAttribute (&lt;/b&gt;which implements&lt;b&gt; IAuthorizationFilter) &lt;/b&gt;and applying the attribute to an action method. The &lt;b&gt;Controller&lt;/b&gt; class itself implements &lt;b&gt;IAuthorizationFilter&lt;/b&gt;, so the easiest way to implement an Authorization Filter is to override the &lt;b&gt;OnAuthorization&lt;/b&gt; method inside your controller class. 

      &lt;div style="border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:35.69%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;height:116px;background-color:#f4f4f4;"&gt;
        &lt;div style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;
          &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; OnAuthorization(AuthorizationContext filterContext)&lt;/pre&gt;

          &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;

          &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   3:&lt;/span&gt;     filterContext.Cancel = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;&lt;/pre&gt;

          &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   4:&lt;/span&gt;     filterContext.Result = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; RedirectResult(&lt;span style="color:#006080;"&gt;&amp;quot;/Home/Login&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

          &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#606060;"&gt;   5:&lt;/span&gt; }&lt;/pre&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;

&lt;blockquote&gt;&amp;#160;&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;u&gt;Action Filter – OnActionExecuting&lt;/u&gt;: If the processing isn’t cancelled above, then the &lt;b&gt;OnActionExecuting&lt;/b&gt; method on the action filter collection is executed. Again as with Authorization Filter, &lt;b&gt;Controller&lt;/b&gt; itself implements &lt;b&gt;IActionFilter&lt;/b&gt; interface, so an &lt;b&gt;OnActionExecuting&lt;/b&gt; method is available to be overridden within the controller class. This is another point where execution of any further action filters and the action itself can be cancelled by setting the result property to an &lt;b&gt;ActionResult&lt;/b&gt; of your choice. &lt;/li&gt;

    &lt;li&gt;&lt;u&gt;Action method&lt;/u&gt; itself is invoked with the parameters supplied by the model binder. &lt;/li&gt;

    &lt;li&gt;&lt;u&gt;Action Filter – OnActionExecuted&lt;/u&gt;: After the execution of the action method, &lt;b&gt;OnActionExecuted&lt;/b&gt; method on the action filter collection (including the &lt;b&gt;OnActionExecuted&lt;/b&gt; method on the controller) is executed. In this method you can get information on any exceptions that were thrown during the action method execution via &lt;b&gt;ActionExecutedContext&lt;/b&gt;.&lt;b&gt;Exception&lt;/b&gt;. Here you have a chance to handle the exceptions and stop further propagation of the exception by using the &lt;b&gt;ActionExecutedContext.ExceptionHandled&lt;/b&gt; property. &lt;/li&gt;

    &lt;li&gt;&lt;u&gt;Exception Filter – OnException:&lt;/u&gt; An exception filter must implement &lt;b&gt;IExceptionFilter&lt;/b&gt; interface. As with other types of filters, it can be applied as an attribute. The controller implements &lt;b&gt;IExceptionFilter&lt;/b&gt; interface and provides access to its functionality via &lt;b&gt;OnException&lt;/b&gt; method that can be overridden within the controller class. This is called if an exception is thrown anywhere during action or result execution. An exception thrown in the Action can be handled in &lt;b&gt;OnActionExecuted&lt;/b&gt; to stop it from being propagated up to this stage. Similarly as will be explained later on, an exception thrown during result execution can be handled inside a &lt;b&gt;ResultFilter&lt;/b&gt; &lt;b&gt;OnResultExecuted&lt;/b&gt; stage to stop it from getting here. &lt;b&gt;ExceptionFilter&lt;/b&gt; offers you the final chance to handle exceptions before the exception is thrown up to Global.asax. &lt;b&gt;HandleErrorAttribute &lt;/b&gt;is an exception filter provided out of the box with the framework to help with exception handling within the controller. &lt;/li&gt;

    &lt;li&gt;&lt;u&gt;Result Filter - OnResultExecuting:&lt;/u&gt; This step occurs before the &lt;b&gt;ActionResult&lt;/b&gt; is executed. A result filter must implement &lt;b&gt;IResultFilter&lt;/b&gt; interface and the &lt;b&gt;Controller&lt;/b&gt; class offers an implementation via the &lt;b&gt;OnResultExecuting&lt;/b&gt; and &lt;b&gt;OnResultExecuted&lt;/b&gt; methods. The request will only get here if there are no unhandled exceptions in the action method and the &lt;b&gt;OnActionExecuted&lt;/b&gt; stage. &lt;/li&gt;

    &lt;li&gt;&lt;u&gt;ActionResult execution&lt;/u&gt; – This is the stage where the &lt;b&gt;ActionResult&lt;/b&gt; is executed and the http response determined. &lt;b&gt;ActionResult&lt;/b&gt; is just an abstract class and is extended by specific type of action results like &lt;b&gt;ViewResult (&lt;/b&gt;for HTML output&lt;b&gt;)&lt;/b&gt;, &lt;b&gt;JsonResult (&lt;/b&gt;For Json output&lt;b&gt;)&lt;/b&gt;, &lt;b&gt;RedirectResult (&lt;/b&gt;an HTTP redirect&lt;b&gt;), ContentResult &lt;/b&gt;(for text output) etc. This is another extensibility point, which allows a custom &lt;b&gt;ActionResult&lt;/b&gt; implementation. See an example here: &lt;a href="http://blog.maartenballiauw.be/post/2008/05/ASPNET-MVC-custom-ActionResult.aspx"&gt;http://blog.maartenballiauw.be/post/2008/05/ASPNET-MVC-custom-ActionResult.aspx&lt;/a&gt; &lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;b&gt;IView and IViewEngine&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;u&gt;Rendering a view &lt;/u&gt;– When the return type from the action is that of a &lt;b&gt;ViewResult&lt;/b&gt; there are two interfaces, &lt;b&gt;IView&lt;/b&gt; and &lt;b&gt;IViewEngine&lt;/b&gt; that get involved. &lt;b&gt;IViewEngine&lt;/b&gt; interface defines the contract for locating a view or a partial view. &lt;b&gt;IView&lt;/b&gt; defines the contract for rendering the view. By default the framework uses &lt;b&gt;WebFormView&lt;/b&gt; and &lt;b&gt;WebFormViewEngine&lt;/b&gt; which process .aspx based views. A custom view processing infrastructure can be implemented by creating custom views/view engines. The &lt;a href="http://www.codeplex.com/MVCContrib"&gt;MVCContrib project on codeplex&lt;/a&gt; provides several ViewEngines including those based on XSLT, Brail and nVelocity. Some more information on creating a custom ViewEngine can be found here: &lt;a href="http://www.singingeels.com/Articles/Creating_a_Custom_View_Engine_in_ASPNET_MVC.aspx"&gt;http://www.singingeels.com/Articles/Creating_a_Custom_View_Engine_in_ASPNET_MVC.aspx&lt;/a&gt; &lt;/li&gt;
  &lt;/ul&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;u&gt;Result Filter – OnResultExecuted:&lt;/u&gt; This is the last step executed within the controller and occurs after the result has been executed and http response produced. If any exceptions are thrown during the result execution, then you’ll have a chance to handle the exception here. If not the exception is bubbled up towards Exception Filters (see Exception Filters - &lt;b&gt;OnException&lt;/b&gt; stage). &lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;

&lt;p&gt;After this stage the http response would have been produced and the control is transferred back to &lt;b&gt;HttpApplication&lt;/b&gt; to carry through the rest of the lifecycle. This concludes our journey through the request processing occurring within the ASP.NET MVC framework. &lt;/p&gt;

&lt;p&gt;This follow-up post explained the passage of a request through the ASP.NET MVC framework and describes how the request is processed through the various stages within. Hopefully it gives a good idea of the ASP.NET MVC lifecycle and extensibility points within it. &lt;/p&gt;
&lt;div id="SocialBookmarks"&gt;&lt;a href="http://del.icio.us/post?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f02%2f11%2fhow-does-asp-net-mvc-work-part-2.aspx&amp;tags=&amp;title=How+does+ASP.NET+MVC+work+%e2%80%93+Part+2" mce_href="http://del.icio.us/post?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f02%2f11%2fhow-does-asp-net-mvc-work-part-2.aspx&amp;tags=&amp;title=How+does+ASP.NET+MVC+work+%e2%80%93+Part+2"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/delicious.gif"&gt;Del.icio.us&amp;nbsp;&lt;/a&gt;&lt;a href="http://digg.com/submit?phase=2&amp;url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f02%2f11%2fhow-does-asp-net-mvc-work-part-2.aspx&amp;title=How+does+ASP.NET+MVC+work+%e2%80%93+Part+2&amp;tags=" mce_href="http://digg.com/submit?phase=2&amp;url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f02%2f11%2fhow-does-asp-net-mvc-work-part-2.aspx&amp;title=How+does+ASP.NET+MVC+work+%e2%80%93+Part+2&amp;tags="&gt;&lt;img border="0" src="/Themes/leanandgreen/images/digg.gif"&gt;Digg It&amp;nbsp;&lt;/a&gt;&lt;a href="http://www.facebook.com/share.php?u=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f02%2f11%2fhow-does-asp-net-mvc-work-part-2.aspx" mce_href="http://www.facebook.com/share.php?u=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f02%2f11%2fhow-does-asp-net-mvc-work-part-2.aspx"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/facebook.gif"&gt;Share on Facebook&amp;nbsp;&lt;/a&gt;&lt;a href="http://www.stumbleupon.com/submit?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f02%2f11%2fhow-does-asp-net-mvc-work-part-2.aspx&amp;title=How+does+ASP.NET+MVC+work+%e2%80%93+Part+2" mce_href="http://www.stumbleupon.com/submit?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f02%2f11%2fhow-does-asp-net-mvc-work-part-2.aspx&amp;title=How+does+ASP.NET+MVC+work+%e2%80%93+Part+2"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/stumble.gif"&gt;Stumble It!&lt;/a&gt;&lt;/div&gt;&lt;img src="http://blogs.charteris.com/aggbug.aspx?PostID=770" width="1" height="1"&gt;</description><category domain="http://blogs.charteris.com/blogs/gopalk/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.charteris.com/blogs/gopalk/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>How does ASP.NET MVC work?</title><link>http://blogs.charteris.com/blogs/gopalk/archive/2009/01/20/how-does-asp-net-mvc-work.aspx</link><pubDate>Tue, 20 Jan 2009 06:56:00 GMT</pubDate><guid isPermaLink="false">0cdfd867-77e4-483c-9e74-84c93cc8eba0:755</guid><dc:creator>gopalk</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.charteris.com/blogs/gopalk/rsscomments.aspx?PostID=755</wfw:commentRss><comments>http://blogs.charteris.com/blogs/gopalk/archive/2009/01/20/how-does-asp-net-mvc-work.aspx#comments</comments><description>&lt;p&gt;If you’ve looked at the ASP.NET MVC framework, you might have wondered how it fits within the rest of the ASP.NET lifecycle. To understand it though, the ASP.NET request lifecycle needs to be understood first.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;What happens when an ASP.NET request is made? &lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;The answer depends on the version of IIS being used. In IIS 5.0 / 6.0, ASP.NET support was accomplished using an isapi extension i.e. &lt;b&gt;aspnet_isapi.dll&lt;/b&gt;. In IIS 5.0 / 6.0 there is a distinct handover of the request from IIS to .NET before any managed code can respond to the request. This is achieved by mapping certain extensions like .aspx, .asmx etc to &lt;b&gt;aspnet_isapi.dll &lt;/b&gt;extension by using application mapping within IIS manager interface.&lt;/p&gt;
&lt;p&gt;But in IIS 7.0 (running in integrated mode) things are different. IIS 7.0 integrates the ASP.NET runtime with the core web server and there is no specific handoff needed from IIS to ASP.NET. Thus for a managed &lt;b&gt;HttpModule&lt;/b&gt; to execute, the request doesn’t have to be routed to ASP.NET first. A managed &lt;b&gt;HttpModule&lt;/b&gt; can be added via IIS manager itself and can be made to execute for both managed and native requests. Similarly a managed &lt;b&gt;HttpHandler&lt;/b&gt; class can be mapped to specific extensions directly via IIS manager (which stores the configuration in applicationHost.config file.) or via the web application’s web.config file. &lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;So what happens when a request gets through to ASP.NET?&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;1. &lt;b&gt;ApplicationManager&lt;/b&gt; and &lt;b&gt;HostingEnvironment&lt;/b&gt; classes are created. &lt;b&gt;ApplicationManager&lt;/b&gt; class manages Applications and their AppDomain for all the applications on the hosting process. &lt;b&gt;ApplicationManager&lt;/b&gt; can be used to do cool things like hosting ASP.NET in your custom process, see here: &lt;a href="http://www.west-wind.com/WebLog/posts/4976.aspx%20"&gt;http://www.west-wind.com/WebLog/posts/4976.aspx&lt;/a&gt; . This is also the stage when any necessary compilation of code in &lt;b&gt;App_Code&lt;/b&gt; folder occurs. &lt;/p&gt;
&lt;p&gt;2. &lt;b&gt;HttpRequest&lt;/b&gt;, &lt;b&gt;HttpResponse&lt;/b&gt; and &lt;b&gt;HttpContext&lt;/b&gt; objects are created and populated. At the end of this stage these objects are usable.&lt;/p&gt;
&lt;p&gt;3. Now the current &lt;b&gt;HttpContext&lt;/b&gt; is assigned to an instance of &lt;b&gt;HttpApplication&lt;/b&gt; (or instance of Global.asax if exists). At the same time any &lt;b&gt;HttpModules&lt;/b&gt; (inherited from parent app or defined in web.config) are initialised. The &lt;b&gt;HttpApplication&lt;/b&gt; class defines a set of stages/events that get executed one by one and carry the processing forward in distinct steps. Note that the &lt;b&gt;HttpModules&lt;/b&gt; that have been initialised will attach themselves to one or more of these lifecycle events defined on &lt;b&gt;HttpApplication&lt;/b&gt; instance.&lt;/p&gt;
&lt;p&gt;4. &lt;b&gt;HttpApplication&lt;/b&gt; lifecycle events fire in succession:&lt;/p&gt;
&lt;p&gt;Note that the list of lifecycle events on &lt;b&gt;HttpApplication&lt;/b&gt; is extensive and the objective here is not to analyse the entire lifecycle, so I’ll skip the parts that are not directly relevant for this exercise. For an extensive look at &lt;b&gt;HttpApplication&lt;/b&gt; lifecycle elements look here:&lt;/p&gt;
&lt;p&gt;IIS7: &lt;a href="http://msdn.microsoft.com/en-us/library/bb470252.aspx"&gt;http://msdn.microsoft.com/en-us/library/bb470252.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;IIS5/6: &lt;a href="http://msdn.microsoft.com/en-us/library/ms178473.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms178473.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first relevant event in the &lt;b&gt;HttpApplication&lt;/b&gt; lifecycle that we need to look at is &lt;b&gt;MapRequestHandler&lt;/b&gt;. Now this step is new in .NET 3.5 but an equivalent step (without the corresponding event) existed before .NET 3.5. It is in this step that an &lt;b&gt;HttpApplication&lt;/b&gt; selects an &lt;b&gt;HttpHandler&lt;/b&gt; to service the request. Now the selection of &lt;b&gt;HttpHandler&lt;/b&gt; will be based on web.config or inherited configuration. The HandlerFactory set in the configuration will be used to acquire an instance of the Handler which is then assigned to the context.&lt;/p&gt;
&lt;p&gt;So for example, if a request is for an ‘aspx’ file, in the &lt;b&gt;MapRequestHandler &lt;/b&gt;stage, &lt;b&gt;HttpApplication&lt;/b&gt; will map ‘.aspx’ request to &lt;b&gt;PageHandlerFactory&lt;/b&gt;. &lt;b&gt;GetHandler&lt;/b&gt; method is then invoked on &lt;b&gt;PageHandlerFactory&lt;/b&gt; which returns an instance of the appropriate &lt;b&gt;Page&lt;/b&gt; class (&lt;b&gt;Page&lt;/b&gt; is basically an &lt;b&gt;HttpHandler&lt;/b&gt; and implements &lt;b&gt;IHttpHandler&lt;/b&gt; interface). This is then attached to the &lt;b&gt;Handler&lt;/b&gt; property of the context class. &lt;/p&gt;
&lt;p&gt;Let’s skip a few more steps and go to the &lt;b&gt;ProcessRequest &lt;/b&gt;stage. By now the request (To be precise the &lt;b&gt;HttpContext&lt;/b&gt; object encapsulating the request.) already has an &lt;b&gt;HttpHandler&lt;/b&gt; assigned to it as seen earlier. The request is now processed here by invoking the &lt;b&gt;ProcessRequest&lt;/b&gt; method on the &lt;b&gt;HttpHandler&lt;/b&gt;.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Wasn’t this about MVC?&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;In MVC, there is no concept of a Page as in a traditional webform page, i.e. the web page requested doesn’t exist on the disk as a file. Instead it’s served up by a special method (‘the Action’) on a special class (‘the Controller’). This is quite a dynamic routing arrangement as it needs to respond to varying URL’s. And if you do not want to use a special extension (like .mvc) for these MVC requests, then you can’t really use an HttpHandler entry in web.config/IIS. (There does exist a handler for .mvc in web.config if you want to use .mvc extension for your MVC requests.) &lt;/p&gt;
&lt;p&gt;So, how does ASP.NET know how to route requests to MVC? The answer lies in web.config. There is a new http module added to modules collection in ASP.NET MVC projects&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;lt;add name=&amp;quot;UrlRoutingModule&amp;quot; type=&amp;quot;System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot; /&amp;gt; &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;This was originally a part of MVC framework but since has been released as a separate assembly. The other part in this routing magic is played by Global.asax &lt;b&gt;RegisterRoutes&lt;/b&gt; method. &lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;routes.MapRoute(&amp;quot;Default&amp;quot;, &amp;quot;{controller}/{action}/{id}&amp;quot;,new { controller = &amp;quot;Home&amp;quot;, action = &amp;quot;Index&amp;quot;, id = &amp;quot;&amp;quot; });&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;MapRoute&lt;/b&gt; is an extension method on &lt;b&gt;RouteCollection&lt;/b&gt; class that can be used to define possible routes. In the background this method sets the routes you define to be handled by &lt;b&gt;MvcRouteHandler&lt;/b&gt; class.&lt;/p&gt;
&lt;p&gt;The &lt;b&gt;UrlRoutingModule&lt;/b&gt; attaches itself to &lt;b&gt;PostResolveRequestCache&lt;/b&gt; and &lt;b&gt;PostMapRequestHandler&lt;/b&gt; events of the &lt;b&gt;HttpApplication &lt;/b&gt;instance and overrides the default behaviour of &lt;b&gt;MapRequestHandler &lt;/b&gt;stage. &lt;b&gt;UrlRoutingModule&lt;/b&gt; does this by searching the &lt;b&gt;RouteCollection&lt;/b&gt; for a route matching the request. If it’s found, the associated &lt;b&gt;RouteHandler&lt;/b&gt; is retrieved from the &lt;b&gt;RouteCollection&lt;/b&gt;. In our case this is an &lt;b&gt;MvcRouteHandler&lt;/b&gt; instance. An instance of &lt;b&gt;MvcHandler&lt;/b&gt; is retrieved from &lt;b&gt;MvcRouteHandler&lt;/b&gt; and assigned as the handler for the current context. Nice thing to note is that &lt;b&gt;RouteCollection&lt;/b&gt; is one of the points where the MVC framework can be extended. This can be done by defining a custom RouteHandler corresponding to the routes (instead of the &lt;b&gt;MvcRouteHandler&lt;/b&gt;). There is some good information here on how to this.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/luisabreu/archive/2008/07/23/the-mvc-framework-the-mvcroutehandler.aspx"&gt;http://msmvps.com/blogs/luisabreu/archive/2008/07/23/the-mvc-framework-the-mvcroutehandler.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As a side note, also note that &lt;b&gt;UrlRoutingModule&lt;/b&gt; will by default ignore any requests that match a file that exists on the disk. Thus if a request for WebForm1.aspx is received and it happens to exist on the disk then route lookup will be skipped for this request. This behaviour can be changed (at your own peril!) by setting routes.RouteExistingFiles = true ;&lt;/p&gt;
&lt;p&gt;Now there might be a case where a custom handler needs to be defined within our MVC web application (For integrating third party products/user controls). This may not exist on the disk and will trigger a route table lookup and a 404 if no matching routes are found. To avoid this, &lt;b&gt;RouteCollection&lt;/b&gt; can be instructed to ignore this specific path in the following way.&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;routes.IgnoreRoute(&amp;quot;&amp;lt;your route&amp;gt;&amp;quot;);&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;So in this post we saw how a request was routed from IIS through to the MVC framework and along the way, an extensibility point was identified. From here it needs to be routed through to the right action on the right controller class, but that could be the topic of an entirely new post! &lt;/p&gt;
&lt;div id="SocialBookmarks"&gt;&lt;a href="http://del.icio.us/post?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f01%2f20%2fhow-does-asp-net-mvc-work.aspx&amp;tags=&amp;title=How+does+ASP.NET+MVC+work%3f" mce_href="http://del.icio.us/post?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f01%2f20%2fhow-does-asp-net-mvc-work.aspx&amp;tags=&amp;title=How+does+ASP.NET+MVC+work%3f"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/delicious.gif"&gt;Del.icio.us&amp;nbsp;&lt;/a&gt;&lt;a href="http://digg.com/submit?phase=2&amp;url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f01%2f20%2fhow-does-asp-net-mvc-work.aspx&amp;title=How+does+ASP.NET+MVC+work%3f&amp;tags=" mce_href="http://digg.com/submit?phase=2&amp;url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f01%2f20%2fhow-does-asp-net-mvc-work.aspx&amp;title=How+does+ASP.NET+MVC+work%3f&amp;tags="&gt;&lt;img border="0" src="/Themes/leanandgreen/images/digg.gif"&gt;Digg It&amp;nbsp;&lt;/a&gt;&lt;a href="http://www.facebook.com/share.php?u=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f01%2f20%2fhow-does-asp-net-mvc-work.aspx" mce_href="http://www.facebook.com/share.php?u=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f01%2f20%2fhow-does-asp-net-mvc-work.aspx"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/facebook.gif"&gt;Share on Facebook&amp;nbsp;&lt;/a&gt;&lt;a href="http://www.stumbleupon.com/submit?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f01%2f20%2fhow-does-asp-net-mvc-work.aspx&amp;title=How+does+ASP.NET+MVC+work%3f" mce_href="http://www.stumbleupon.com/submit?url=http%3a%2f%2fblogs.charteris.com%2fblogs%2fgopalk%2farchive%2f2009%2f01%2f20%2fhow-does-asp-net-mvc-work.aspx&amp;title=How+does+ASP.NET+MVC+work%3f"&gt;&lt;img border="0" src="/Themes/leanandgreen/images/stumble.gif"&gt;Stumble It!&lt;/a&gt;&lt;/div&gt;&lt;img src="http://blogs.charteris.com/aggbug.aspx?PostID=755" width="1" height="1"&gt;</description><category domain="http://blogs.charteris.com/blogs/gopalk/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blogs.charteris.com/blogs/gopalk/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.charteris.com/blogs/gopalk/archive/tags/IIS/default.aspx">IIS</category></item></channel></rss>