Article content
In the last section we talked about the way that you can dynamically add a route before httpmodules initialization to customize your own HttpHandler and ultimately take over the request, is that MVC implemented? In this chapter we will analyze the relevant MVC source code to verify our problem.
Create a MVC3 Web application first, and select the default template to include HomeController and AccountController by default when you create it. We know that MVC has to take over the request before it can be handled by these controllers. Let's go to the Global.asax.cs file first to see the code (define the takeover request before initializing HttpModule, so we can only come here to find the code (or the use of Webactivator and other features to dynamically add), Global.asax.cs file in the code is very small, but we need to Things, first find a line of code in the Application_Start method:
RegisterRoutes (routetable.routes);
This line of code, see the method name called RegisterRoutes is the meaning of the registered route, but why the parameter is the global routetable.routes collection it? Find the RegisterRoutes method to see the specific content:
Public Static voidregisterroutes (routecollection routes) {routes. Ignoreroute ("{Resource}.axd/{*pathinfo}"); Routes. MapRoute ("Default",//Route name "{Controller}/{action}/{id}",//URL with Parameters New{controller ="Home", action ="Index", id = urlparameter.optional}//Parameter Defaults );}
The method has 2 lines of code, the first line is to ignore a route (we do not see this), the second line is to use the Maproute method to register a new route, the default is mapped to the home Controller's index action, we may think of, The Maproute method of RouteCollection (that is, the routetable.routes just passed in) is to provide the entrance to what we call a takeover request, but how do you get MVC's own HttpHandler in? We go to this maproute method (need to install Reshaper to find the MVC source code), adjusted to the MVC Routecollectionextensions class, Discover that Maproute is not a routecollection method, but an extension method provided in the MVC source code as follows:
Public StaticRoute MapRoute ( ThisRouteCollection routes,stringNamestringUrlObjectDefaultsObjectConstraintsstring[] namespaces) { if(Routes = =NULL) { Throw NewArgumentNullException ("Routes"); } if(url = =NULL) { Throw NewArgumentNullException ("URL"); } Route Route=NewRoute (URL,NewMvcroutehandler ()) {Defaults=Newroutevaluedictionary (defaults), Constraints=Newroutevaluedictionary (constraints), Datatokens=Newroutevaluedictionary ()}; if((Namespaces! =NULL) && (namespaces. Length >0) ) {route. datatokens["Namespaces"] =namespaces; } routes. ADD (name, route); returnRoute;}
The main function of the code is to new a route and then add the route to the static collection Routetable.routes we just mentioned so that we can use it later when we find handler, OK, this step is in line with the analysis of our previous chapters.
Next, how the route is new, the parameters in the code are the URLs we know, and a Mvcroutehandler instance, and this step is in line with our previous analysis, So let's take a look at how Mvcroutehandler's Gethttphandler method is implemented to get Mvchandler:
Public classMvcroutehandler:iroutehandler {Privateicontrollerfactory _controllerfactory; PublicMvcroutehandler () {} PublicMvcroutehandler (icontrollerfactory controllerfactory) {_controllerfactory=controllerfactory; } protected VirtualIHttpHandler Gethttphandler (RequestContext requestcontext) {RequestContext.HttpContext.SetSessionStateBeh Avior (Getsessionstatebehavior (RequestContext)); return new Mvchandler (requestcontext); } protected Virtualsessionstatebehavior Getsessionstatebehavior (RequestContext requestcontext) {stringControllername = (string) requestcontext.routedata.values["Controller"]; Icontrollerfactory controllerfactory= _controllerfactory??ControllerBuilder.Current.GetControllerFactory (); returnControllerfactory.getcontrollersessionbehavior (RequestContext, controllername); } #regionIroutehandler MembersIHttpHandler iroutehandler.gethttphandler(RequestContext requestcontext) {return Gethttphandler (requestcontext); } #endregion }
Look at the above bold code, Mvcroutehandler in the implementation of the Iroutehandler Gethttphandler, the method calls the Mvcroutehandler itself defined Gethttphandler virtual method, And in this virtual method we see a very important and long-awaited code--return Mvchandler instance, probably look at Mvchandler this class, get it is what we guess: Inherit from the IHttpHandler interface of a class, and also inherit the IHttpAsyncHandler interface, we first regardless of how the Mvchandler interior is implemented, but our previous chapters of the entire analysis has finally been verified, it is said here to get the MVC dedicated processing handler, It then calls its BeginProcessRequest method into MVC's own pipeline for processing.
At this point, we finally figured out how MVC would take over the entire ASP. NET runtime, and it should probably be clear how the entire ASP runtime works, as for the way Mvchandler is implemented, We will analyze each line of code in the following chapters, and today we have a small task, that is: After reading the implementation of the MVC mechanism, we can write a custom HttpHandler through the route dynamic registration in order to achieve our own custom extension, Let's try to do it.
First step: Establish HttpHandler class
Public classTomhandler:ihttphandler { PublicTomhandler (RequestContext requestcontext) {// do nothing } Public Virtual voidProcessRequest (HttpContext context) {stringURL =context. Request.Url.AbsoluteUri; Context. Response.Write ("The current address is:"+URL); Context. Response.End (); //We don't do anything here. Only the URL address is output } Public Virtual BOOLisreusable {Get { return false; } } }
Step Two: Establish Routehandler class
Public class tomroutehandler:iroutehandler{ IHttpHandler iroutehandler.gethttphandler (RequestContext RequestContext) { returnnew Tomhandler (RequestContext); }}
In the Gethttphandler implementation, return the Tomhandler instance that we defined.
Step three: Sign up for our route and Routehandler
protected void Application_Start (object sender, EventArgs e) { new Route ("Tom/{other} "new Tomroutehandler ()); ROUTETABLE.ROUTES.ADD (route);}
We set the URL to be prompt whenever you access any file or subdirectory under the Tom folder. Here are my test results:
Visit: http//localhost/tom/
Result: No indication of our expected results (reason is not conforming to our rules)
Visit: http//localhost/tom/123/
Result: The output is normal (indicating that Tomhandler has taken over the request)
Visit: http//localhost/tom/123.aspx?id=123
Result: The output is normal (also indicates that Tomhandler has taken over the request)
Create a real Tom folder, then create a index.html file inside it (content 123), and then access the http//localhost/tom/ Index.html, the rules conform to our route definition, but the output is not the result we expected, but 123, what's going on? Remember the Getroutedata method of RouteCollection mentioned in the previous chapter? This method is the first to determine whether the URL corresponding to the file is real, if there is direct output, if it does not exist to find routedata data, which explains the above index.html path why is not the reason we expect the result?
Note: If you create a index.aspx file and write Response.Write code output 123 in the Index.aspx.cs file, the file will also be executed according to the normal cycle of the ASPX page (that is, the output 123 string), if you are in < The httphandlers node in the system.web> removes the *.aspx matching settings with the Remove command, which results in only the output of the string from the Index.aspx file (including any C # code embedded inside).
In conclusion, we have already learned how Mvchandler is taking over the request, and have done a simple example to verify the mechanism. Looking back at so many previous articles, we should probably have an overall understanding of the ASP. NET RunTime, Pipeline, and ASP. NET MVC entry points.
Synchronization and recommendations
This article has been synchronized to the directory index: Thelittle Thing before MVC series
MVC before the point of the article series, including the original, translation, reprint and other types of articles, if it is useful to you, please recommend supporting a, to the power of the uncle writing.