MVC Learning Notes---MVC life cycle and pipelines

Source: Internet
Author: User

Asp. NET and ASP. HttpApplication request processing pipelines have common parts and differences, this series will experience the 19 key aspects of the ASP. Web MVC request processing pipeline life cycle.

① take IIS6.0 as an example, the first is to maintain a working process by w3wp.exe


② If this is the first time loading, the. NET runtime is loaded by Aspnet_isapi.dll


③ A worker process has an application pool, which can host more than one application domain appdomain


④http.sys receive requests, create application domain appdomain through application domain factory appdomainfactory


⑤ a isapiruntime is loaded and a Isapiworkerrequest object is created to encapsulate the current HTTP request and pass the Isapiworkerrequest object to the HttpRuntime runtime of ASP. HTTP request begins entry to ASP. NET Request Pipeline


That is, httpruntime is the entry for the ASP. NET request pipeline. When the request comes in, first enter httpruntime, and the httpruntime decides how to handle the request. By default, the HttpRuntime node is not explicitly defined in Machine.config and Web. config, but the node has a default value, as follows:

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.