In general, we can change the default value of the HttpRuntime node in Web. config as follows:
<configuration> <system.web>
⑥httpruntime maintains a httpapplication pool, and when an HTTP request comes in, pick an available HttpApplication processing request from the pool
The HttpApplication has 19 pipeline events, namely:
1, the Beginrequest:http pipeline starts processing the request, it triggers BeginRequest event 2, AuthenticateRequest: The security module triggers the event when the request is authenticated 3, Postauthenticaterequest: The security module triggers the event when the request is authenticated 4, AuthorizeRequest: The security module triggers the event 5 when the request process is authorized. Postauthorizerequest: The security module triggers the event when it authorizes the request process 6, Resolverequestcache: The cache module triggers the event when it responds directly to the request process by using the cache 7, Postresolverequestcache: The cache module uses the cache to respond directly to the request process after triggering the event 8, Postmaprequesthandler: For access to different resource types, ASP. NET has different HttpHandler for its process processing. For each request, ASP. NET chooses to match the appropriate HttpHandler type according to the extension, triggering the event after a successful match 9, AcquireRequestState: The state management module gets the event 10 that is triggered based on the current request's corresponding state (such as sessionstate). Postacquirerequeststate: The state management module acquires the event 11, based on the corresponding state (such as sessionstate) of the current request. PreRequestHandlerExecute: Triggers the event before HttpHandler 12, PostRequestHandlerExecute: Triggers the event after HttpHandler is implemented 13, ReleaseRequestState: The State Management module releases the corresponding state based on the current request when the event is triggered 14, Postreleaserequeststate: The State Management module releases the corresponding state based on the current request after the event 15 is triggered, Updaterequestcache: The cache module fires the event 16 when the corresponding HttpHandler processing request is saved to the output cache. Postupdaterequestcache: The cache module fires the event after the HttpHandler processing request has been saved to the output cache 17, Logrequest: This event is triggered when the process log is currently requested 18, Postlogreques: Triggers the event after the current request process is logged 19, EndRequest: The event is triggered after the entire request processing is completed
We can customize the pipeline events in the global profile global.asax, according to the agreed rules application_{event Name}:
⑦ httpruntime Create a HttpContext object based on the Isapiworkerrequest object
⑧httpapplicationfactory create a new or get an existing, available HttpApplication object from the HttpApplication pool
HttpApplication's work includes:
Load all HttpModule when initializing
Receiving requests
Different events are raised at different stages, allowing HttpModule to subscribe to events to be added to the requested process
Obtain a IHttpHandler instance at a specific stage, and eventually submit the request to a specific ihttphandler to implement
⑨ Next, that's when httpmodules plays a role.
All httpmodules implement the IHttpModule interface:
public interface ihttpmodule{ void Init (HttpApplication app); void Dispose ();}
As can be seen, Httomodules is the Init method that subscribes to all events of HttpApplication based on the passed-in HttpApplication type parameter.
We customize a HttpModule:
public class testmodule:ihttpmodule{public void Dispose () {} public void Init (HttpApplication app) { App. Postacquirerequeststate + = new EventHandler (app_postacuiredrequeststate); App. PreRequestHandlerExecute + = new EventHandler (app_prerequesthandlerexecute); } void App_prerequesthandlerexecute (object sender, EventArgs e) { //todo: } void App_ Postacquiredrequeststate (object sender, EventArgs e) { //todo: }}
⑩ when a request matches a rule, ASP. NET calls the GetHandler method of the matching httphandlerfactory to get a HttpHandler instance, and finally a HttpHandler instance to process the current request, generating the response content
All httphandlers Implement the IHttpHandler interface:
public interface ihttphandler{ bool Isreusable{get;} void ProcessRequest (HttpContext context);}
For example, we can customize a HttpHandler to respond to a specific type of request:
public class login:ihttphandler{public void ProcessRequest (HttpContext context) { context. Response.ContentType = "Text/plain"; String username = context. request.form["name"]; String Password = context. request.form["Password"]; if (password= "Sth") { System.Web.Security.FormsAuthentication.SetAuthCookie (username, false); Context. Response.Write ("OK"); } else { context. Response.Write ("Username and password is incorrect");}}}
The entrance to ⑾asp.net MVC is in UrlRoutingModule, which is the 7th pipeline event Postresolverequestcahce subscribed to HttpApplication, in other words, The request was intercepted at the 7th pipeline event in Htttpapplication.
Urlroutemodlue implements the IHttpModule:
public class urlroutingmodule:ihttpmodule{//Fields private static readonly Object _contextkey = new Object (); private static readonly Object _requestdatakey = new Object (); Private RouteCollection _routecollection; Methods protected virtual void Dispose () {} protected virtual void Init (HttpApplication application) { if (application. Context.items[_contextkey] = = null) {application. Context.items[_contextkey] = _contextkey; Application. Postresolverequestcache + = new EventHandler (this. Onapplicationpostresolverequestcache); }} private void Onapplicationpostresolverequestcache (object sender, EventArgs e) {HttpContextBase conte XT = new Httpcontextwrapper (((HttpApplication) sender). Context); This. Postresolverequestcache (context); } [Obsolete ("This method is Obsolete. Override the Init method to use the Postmaprequesthandler event. ")] public virtual void Postmaprequesthandler (HttpContextBase context) {} public virtual void Postresolverequestcache (HttpContextBase context) {Ro Utedata Routedata = this. Routecollection.getroutedata (context); if (routedata! = null) {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)) {RequestContext RequestContext = new RequestContext (Contex T, 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) {if (! formsauthenticationmodule.formsauthrequired) {throw new HttpException (0x191, SR . GetString ("Assess_denied_description3")); } urlauthorizationmodule.reporturlauthorizationfailure (HttpContext.Current, this); } else {context. Remaphandler (HttpHandler); }}}} void Ihttpmodule.dispose () {this. Dispose (); } void Ihttpmodule.init (HttpApplication application) {this. Init (application); }//Properties public routecollection routecollection {get {if (this._routecollectio n = = null) {this._routecollection = routetable.routes; } return this._routecollection; } set {this._routecollection = value; } }}
UrlRoutingModule is configured in Web. config or the default Web. config:
⑿ and before the request arrives at UrlRoutingModule, we have configured the following in the global file
public class MvcApplication:System.Web.HttpApplication { protected void Application_Start () { ...... Bundleconfig.registerbundles (bundletable.bundles); } } public class Routeconfig {public static void RegisterRoutes (RouteCollection routes) { routes. Ignoreroute ("{resource}.axd/{*pathinfo}"); Routes. MapRoute ( name: "Default", URL: "{controller}/{action}/{id}", defaults:new {controller = "Home", Action = "Index", id = urlparameter.optional} ); } }
This means that the route is registered to routecollection through the Maproute () method at the first pipeline event beginrequest of HttpApplication. In practice, UrlRoutingModule is getting routes through the static properties of RouteTable RouteCollection.
⒀ when the request arrives at UrlRoutingModule, UrlRoutingModule takes out the controller, action and other routedata information in the request, matches all the rules in the routing table, if matching, Give the request to Iroutehandler, namely Mvcroutehandler
Mvcroutehandler is used to generate mvchandler that implements the IHttpHandler interface:
Namespace system.web.routing{public interface Iroutehandler { IHttpHandler Gethttphandler ( RequestContext requestcontext);} }
UrlRoutingModule how to hand over the request to Mvcroutehandler?
By analyzing the source code of UrlRoutingModule, you can see:
Obtaining Routedata instances that encapsulate routing information through the static method of RouteCollection Getroutedata
Routedata Routedata = this. Routecollection.getroutedata (context);
And get Mvcroutehandler from Routedata.
Iroutehandler Routehandler = Routedata.routehandler;
Why is it possible to get Mvcroutehadnler from Routedata?
Because when we registered the route using the Maproute () method in HttpApplication's first pipeline event, the Mvcroutehandler was injected into the route through the route class's constructor.
public static Route MapRoute (this routecollection routes, string name, string URL, object defaults, object constraints, St Ring[] namespaces) { if (routes = = null) { throw new ArgumentNullException ("routes"); } if (url = = null) { throw new ArgumentNullException ("url"); } Route route = new route (URL, New Mvcroutehandler ()) { Defaults = new RouteValueDictionary (Defaults), Constraints = new RouteValueDictionary (constraints), datatokens = new RouteValueDictionary () }; if (namespaces! = null) && (namespaces. Length > 0)) { route. Datatokens["namespaces"] = namespaces; } Routes. ADD (name, route); return route; }
⒁mvcroutehandler, hand over the request to Mvchandler.
or from UrlRoutingModule source can be seen, through the HttpHandler Gethttphandler () method to achieve the IHttpHandler interface Mvchandler:
IHttpHandler HttpHandler = Routehandler.gethttphandler (RequestContext); context. Remaphandler (HttpHandler);
Mvchandler part of the source code is:
public class Mvchandler:ihttpasynchandler, IHttpHandler, irequiressessionstate{protected internal virtual void P Rocessrequest (HttpContextBase HttpContext) {securityutil.processinapplicationtrust () = {IController controller; Icontrollerfactory Factory; Processrequestinit (HttpContext, out controller, out factory);//Initialize controllerfactory try { Controller. Execute (RequestContext); } finally {factory. Releasecontroller (Controller); } }); } private void Processrequestinit (HttpContextBase HttpContext, out IController controller, out Icontrollerfactory Factory) {bool isrequestvalidationenabled = validationutility.isvalidationenabled (httpcontext.current); if (isrequestvalidationenabled = = True) {Validationutility.enAbledynamicvalidation (HttpContext.Current); } addversionheader (HttpContext); Removeoptionalroutingparameters (); String controllername = RequestContext.RouteData.GetRequiredString ("Controller"); Factory = Controllerbuilder.getcontrollerfactory (); Controller = Factory. Createcontroller (RequestContext, controllername); if (Controller = = null) {throw new InvalidOperationException (String.Format (cultureinfo.currentculture,mvcres Ources. Controllerbuilder_factoryreturnednull,factory. GetType (), controllername)); } }}
⒂ from the above can be seen: first through the static method of Controllerbuilder Getcontrollerfactory get to achieve Icontrollerfactory interface Controllerfactory, The controller name is then obtained from the routing data in the context, and the controller that implements the IController interface is created accordingly
Controller is derived from Controllerbase, and Controllerbase implements the IController interface. Controllerbase part of the source code is as follows:
Public abstract class controllerbase:icontroller{ protected virtual void Execute (RequestContext requestcontext) c1/>{ if (RequestContext = = null) { throw new ArgumentNullException ("RequestContext"); } if (Requestcontext.httpcontext = = null) { throw new ArgumentException ( mvcresources.controllerbase_ Cannotexecutewithnullhttpcontext, "RequestContext"); } Verifyexecutecalledonce (); Initialize (RequestContext); using (Scopestorage.createtransientscope ()) { executecore (); } } protected abstract void Executecore (); ......}
It can be viewed as:
The Execute () method of the base class Controllerbase is executed each time the controller is called
The Execute () method also calls the abstract method of Executecore ()
Executecore () The implementation of this abstract method is defined in the controller
The Executecore () method in the controller invokes the Invokeaction () method of Actioninvoker
⒃actioninvoker Firing Action Method
The Actioninvoker implements the Iactioninvoker interface:
public interface iactioninvoker{ bool Invokeaction (ControllerContext ControllerContext, String actionname);}
The default actioninvoker for MVC is controlleractioninvoker.
In the controller class, an attribute Actioninvoker of type iactioninvoker is provided, and when the Executecore () method is executed, the Actioninvoker call Invokeaction () method to fire the action. As follows:
public class controller{... Private Iactioninvoker _actioninvoker; Public Iactioninvoker actioninvoker { get { if (_actioninvoker = = null) { _actioninvoker = Createactioninvoker (); } return _actioninvoker; } Set { _actioninvoker = value; } } Protected virtual Iactioninvoker Createactioninvoker () { return new Controlleractioninvoker (); public override void Executecore () { actioninvoker.invokeaction (...); } .....}
Actioninvoker will need information about the Controller and action when executing the Invokeaction () method, in fact, the controller information (such as the controller's name, type, contained action, etc.) Encapsulated in the Controllerdescriptor class, action information (such as the name of the action, parameters, attributes, filters, and so on) is encapsulated in the actiondescriptor.
In addition, Actiondescriptor provides a findaction () method to find the action that needs to be executed.
⒄actioninvoker in the Execute Invokeaction () method returns ActionResult
ActionResult is an abstract class:
Public abstract class actionresult{public abstract void Executeresult (ControllerContext context);}
If the ActionResult is non-viewresult, such as Jsonresult, Contentresult, the content will be delivered directly to the response response stream and displayed to the client; Will go to the next render view link.
⒅viewengine find the view that needs to be rendered
The default is the Razor view engine and the Web Form view engine, which implements the Iviewengine interface.
Iviewengine interface Method:
Findpartialview
Findview
Releaseview
If you want to create a custom view Engine, you only need to derive from the Virtualpathproviderviewengine class.
⒆view is loaded into the webviewpage<tmodel> type and renders the generated HTML
Call Viewresult's Executeresult () method to render HTML through the iview render () method.
Public abstract class viewresultbase:actionresult{public override void Executeresult (ControllerContext context) {if (context = = null) {throw new ArgumentNullException ("context"); } if (String.IsNullOrEmpty (ViewName)) {ViewName = context. Routedata.getrequiredstring ("action"); } viewengineresult result = null; if (view = = null) {//gets to Viewengineresult through the view engine, the template page "aspx" is loaded as webviewpage<tmodel> result = Findview (context); View = result. View; } TextWriter writer = context. HttpContext.Response.Output; ViewContext viewcontext = new ViewContext (context, View, ViewData, TempData, writer); View.render (ViewContext, writer); if (result! = null) {result. Viewengine.releaseview (context, View); } }}
void Application_Start (object sender, EventArgs e) {}void Application_End (object sender, EventArgs e) {}void application_ Error (object sender, EventArgs e) {}void Session_Start (object sender, EventArgs e) {}void Session_End (object sender, Event Args e) {} ...
MVC Learning Notes---MVC life cycle and pipelines