Asp. NET runtime details the previous article

Source: Internet
Author: User

Speaking of the life cycle of ASP, there are many introductions on the Internet. I've seen a few of these blogs before, but I feel like I've seen a lot of them, and when I look at them I seem to understand that after a while I forget. So, recently Heavi spent some time studying the source code of ASP, and mastering the life cycle of the ASP through the code level. The code version that is parsed is ASP. NET 5.

Life Cycle Entry HttpRuntime

The ingress processing of HTTP requests in httpruntime is complicated, and it is simple to provide two parameters for the subsequent processing flow: Iis7workerrequest and HttpContext. These two parameters are generated after a direct call to the Httpruntime.processrequestnotification (WR, HttpContext) method, which executes the entire process of the HTTP request.
So, let's start with the processrequestnotificationprivate approach. The code is as follows:

Privaterequestnotificationstatus processrequestnotificationprivate (iis7workerrequest WR, HttpContext context) { Requestnotificationstatus pending=requestnotificationstatus.pending; if(context. Needtoinitializeapp ()) {context.                Response.initresponsewriter (); ApplicationInstance=httpapplicationfactory.getapplicationinstance (context); HttpApplication Application= ApplicationInstance asHttpApplication; if(Application! =NULL) {application.                Assigncontext (context); }} WR.            Synchronizevariables (context); if(Context. ApplicationInstance! =NULL)            {                if(Context. Applicationinstance.beginprocessrequestnotification (Context, This. _requestnotificationcompletioncallback). completedsynchronously) {Pending=requestnotificationstatus.continue; }            }            Else if(ApplicationInstance! =NULL) {applicationinstance.processrequest (context); Pending=requestnotificationstatus.finishrequest; }            Else{Pending=requestnotificationstatus.continue; }            if(Pending! =requestnotificationstatus.pending) { This. Finishrequestnotification (WR, context,refpending); }            returnpending; }

The main processes included in this method are:
1. Initialize the operating environment: Ensurefirstrequestinit. Verify that the application is the first request, if it is necessary to initialize the runtime environment, including initializing the configuration, application pool, loading the DLL under the bin, and so on.
2. Initialize the Response object: Context.Response.InitResponseWriter.
3. Initialize the Application object: Httpapplicationfactory.getapplicationinstance (context).
4. Execute the request process: context. Applicationinstance.beginprocessrequestnotification.
5. Complete the request notification: Finishrequestnotification.
For the main process above, I use a flowchart to indicate that it may be more intuitive. The flowchart is as follows:

Now that you know the 5 main steps above, let's take a detailed description of the specifics of each step.

Initializing the operating environment

By executing the Ensurefirstrequestinit method to initialize the operating environment of our entire application, what exactly is initialized? Let's look at the source code for the method below:

Private voidEnsurefirstrequestinit (HttpContext context) {if( This. _beforefirstrequest) {                Lock( This)                {                    if( This. _beforefirstrequest) {                         This. _firstrequeststarttime =Datetime.utcnow;  This.                        Firstrequestinit (context);  This. _beforefirstrequest =false; Context. Firstrequest=true; }                }            }        }

The code is so few lines, it is obvious that the source code inside the main line is: this. Firstrequestinit (context). This means that the initialization of the operating environment is actually performed in this method. I put the code in the Firstrequestinit method briefly summed up, the following is the core of the code flow:
1. Initialize the Web configuration: Inithttpconfiguration ().
We often read configuration information from ConfigurationManager's appsettings and connectionstrings, These configuration information is the Inithttpconfiguration method read from the IIS environment and the Web environment to the memory provided to the program for use.
2. Temporary folder Write permission to judge: Checkaccesstotempdirectory ().
The simple understanding is that the entire Web environment needs to save some files to the temporary folder in the runtime, so we must ensure that our web environment has temporary folder Write permission.
3. Initialize the request queue: Initrequestqueue ().
Follow the server CPU environment to automatically or manually configure the limit for request process queues, if manual configuration is required to configure the Processmodelsection section in Web. config.
4. Health Monitoring System operating Environment: Healthmonitoringmanager.starthealthmonitoringheartbeat ().
Starts a timer that detects compile errors, unhandled exceptions, logon failures, and so on, and logs to the Windows event log, the SQL Server database, and the Trace Output window. We can initialize the detection mechanism by configuring the Healthmonitoringsection module in Web. config.
5. Constrain the IIS folder: Restrictiisfolders (context).
The function that executes the ISAPI interface (what to do, is not clear at this time).
6. Load the assembly under Bin: Preloadassembliesfrombin ().
Loads all the assemblies for the bin and subdirectories under the bin.
7. Request a header check to prevent injection attacks: this. Initheaderencoding ().

The run environment initialization process flowchart is as follows:

Initializing the Response object

    This step is an operation that initializes the Reponse.output output object that we commonly use.

Initialize Application object

    Executes the GetApplicationInstance method of the HttpApplicationFactory factory to initialize the Application object. Paste the code First:

 internal  static   IHttpHandler GetApplicationInstance (HttpContext context) { // ...            Omit other code   _theapplicationfactory.ensureinited ();            _theapplicationfactory.ensureappstartcalled (context);  return   _        Theapplicationfactory.getnormalapplicationinstance (context); }

The first line of code executes the factory's Ensureinited method, gets the path where the Global.asax file resides, and compiles it. After compiling, start detection to see if the Global.asax file is updated, and if an update is available, the Web app will be stopped.
The second line of code executes the factory method ensureappstartcalled (context), creates a special HttpApplication instance, triggers the Applicationonstart event, executes the Global_ The Application_Start event in asax, the newly created special HttpApplication instance, is recycled after the event has been processed.
The third line of code executes the factory method Getnormalapplicationinstance (context), creating application objects that we often use in Web applications. Since it is the application object we often use, the Getnormalapplicationinstance method should be more than just a simple creation step. Let's take a look at the code for the Getnormalapplicationinstance method:

PrivateHttpApplication Getnormalapplicationinstance (HttpContext context) {HttpApplication State=NULL; Lock( This. _freelist) {                if( This. _numfreeappinstances >0) { state= (HttpApplication) This. _freelist.pop ();  This. _numfreeappinstances--; if( This. _numfreeappinstances < This. _minfreeappinstances) {                         This. _minfreeappinstances = This. _numfreeappinstances; }                }            }            if(state = =NULL) { state= (HttpApplication) httpruntime.createnonpublicinstance ( This. _theapplicationtype); using(NewApplicationimpersonationcontext ()) {State. Initinternal (Context, This. _state, This. _eventhandlermethods); }            }            returnState ; }

This code we have to analyze, which contains what we often call "application pool", reflected in the code is the _freelist collection, in the acquisition of Application object, the first _freelist to find the Idle Application object, Returns a free object directly if one is available, or if no httpruntime.createnonpublicinstance (This._theapplicationtype) method is used to create a Application object. After creation, call the Initinternal method to perform the initialization operation.

The Initinternal method is more important, it initializes our httpmodules, and constructs more than 20 pipeline execution steps for HTTP requests. The specific content of the Initinternal method execution is quite large, I will be a separate chapter to introduce. However, to make a point, this method creates a concrete pipe management object Stepmanager, which is used in the next step of the execute request process.

Executing the request process

When the initialization operation is finished, we should process our request, and the Beginprocessrequestnotification method of the Application object contains the processing of the request. Look at the code:

InternalIAsyncResult Beginprocessrequestnotification (HttpContext context, AsyncCallback cb) {if( This. _context = =NULL)            {                 This.            Assigncontext (context); } context. Currentmoduleeventindex= -1; Httpasyncresult result=NewHttpasyncresult (CB, context); Context. Notificationcontext.asyncresult=result;  This. Resumesteps (NULL); returnresult; }

The Httpasyncresult method creates an object that holds our callback events. Wait until the Resumesteps method finishes executing and then callback the Httpasyncresult event. Next look at the specifics of the Resumesteps method. The code is simple, as follows:

Private void resumesteps (Exception error)        {            this. _stepmanager.resumesteps (Error);        }

There is a _stepmanager object in the code, and in the previous step "initializing the Application object" we mentioned that the Stepmanager,stepmanager entity object was also created in that step. The Resumesteps method initiates more than 20 steps of the HTTP request execution pipeline. So, what exactly does Stepmanager contain? Let's look at his definition:

 internal  abstract  class   Stepmanager { internal< /span> abstract   Buildsteps (WaitCallback stepcallback);  internal  abstract  void   Initrequest ();  internal  abstract  void   Resumesteps (Exception error); }

Stepmanager is an abstract class that defines three abstract methods, Buildsteps (build Steps) and resumesteps (execution steps) We already know, Initrequest used to initialize the request information. Stepmanager a total of two implementation classes: Applicationstepmanager and Pipelinestepmanager. Applicationstepmanager is the IIS6 and IIS7 Classic mode execution Step management object, Pipelinestepmanager is IIS7 's execution step management
Object. These two objects are described in more detail in the next section.

Complete Request Notification

Finishrequestnotification mainly do aftercare work, the code is as follows:

Private voidFinishrequestnotification (Iis7workerrequest WR, HttpContext context,refrequestnotificationstatus status) {HttpApplication applicationinstance=context.            ApplicationInstance; Context. Reportruntimeerrorifexists (refstatus); INTPTR RequestContext=WR.            RequestContext; BOOLSendheaders =unsafeiismethods.mgdislastnotification (RequestContext, status); Try{context.            Response.updatenativeresponse (sendheaders); }            Catch(Exception Exception) {}if(sendheaders) {context.            Finishpipelinerequest (); }            if(Status! =requestnotificationstatus.pending) {Pipelineruntime.disposehandler (context, RequestContext            , status); }        }

You can see from the code that the Finishrequestnotification method records a run-time exception and invokes the context. The Finishpipelinerequest method completes the entire request, releases the requests, response, and application objects.

Summarize

Through the analysis of the above steps, the requested entry is in httpruntime. After the first HTTP request occurs, httpruntime initializes the entire Web environment and then creates HttpApplication from the HttpApplication factory class HttpApplicationFactory. The HttpApplication entity object constructs the request pipeline (Pipeline) step through the Stepmanager Buildsteps method and then executes all the pipeline events through the Resumesteps method.
The next section focuses on the construction and execution details of the Tube pipeline step and the life cycle of the page, so stay tuned!

Asp. NET runtime details the previous article

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.