Main categories:
System. Web. httpruntime
System. Web. httpapplicationfactory
System. Web. httpapplication
System. Web. Compilation. buildmanager
System. Web. Compilation. applicationbuildprovider
System. Web. Compilation. buildproviderscompiler
System. Web. UI. pagehandlerfactory
Brief request processing flowchart:
Analysis:
When we open a browser to ASP. when a request is initiated on an Asp.net page of the net 2.0 website, IIS receives the request first on the server side. When IIS sees the request as an Asp.net page, I am very happy because this request does not need to be processed, to ASP. net ISAPI. The ASP. NET prepare process is too tired to complete the task well. ASP. NET isapiwill give another job and change to a new aspnet_wp.exe to handle the job.
The main task of aspnet_wp.exe is to send requests to a series of managed objects called HTTP pipelines. If ASP. NET isapiis used as the sales manager, aspnet_wp.exe is the production manager, and HTTP pipeline is the Production Pipeline. The supervisor will hand over the order (HTTP request) to the httpruntime team's staff processrequest (httpworkerrequest wr). According to the internal division of labor, httpruntime will eventually be produced in the pipeline by processrequestinternal (httpworkerrequest wr, so processrequestinternal (httpworkerrequest wr) is the focus of our analysis.
First, let's take a look at the processrequestinternal (httpworkerrequest wr) code:
Private void processrequestinternal (httpworkerrequest wr) <br/>{< br/> // Initialize an httpcontext instance <br/> httpcontext extradata = new httpcontext (WR, false ); <br/> Wr. setendofsendnotification (this. _ asyncendofsendcallback, extradata); <br/> interlocked. increment (ref this. _ activerequestcount); <br/> hostingenvironment. incrementbusycount (); <br/> // initialize the first request <br/> try <br/>{< br/> This. ensu Refirstrequestinit (extradata); <br/>}< br/> catch <br/>{< br/> If (! Extradata. request. isdebuggingrequest) <br/>{< br/> throw; <br/>}< br/> // initialize the httpwriter instance <br/> extradata. response. initresponsewriter (); <br/> // create an httpapplication instance <br/> ihttphandler applicationinstance = httpapplicationfactory. getapplicationinstance (extradata); <br/> If (applicationinstance = NULL) <br/>{< br/> throw new httpexception (Sr. getstring ("unable_create_app_object"); <br/>}< br/> If (etwtrace. istraceenabled (5, 1) <br/>{< br/> etwtrace. trace (etwtracetype. etw_type_start_handler, extradata. workerrequest, applicationinstance. getType (). fullname, "Start"); <br/>}< br/> If (applicationinstance is ihttpasynchandler) <br/>{< br/> ihttpasynchandler handler2 = (ihttpasynchandler) applicationinstance; <br/> extradata. asyncapphandler = handler2; <br/> handler2.beginprocessrequest (extradata, this. _ handlercompletioncallback, extradata); <br/>}< br/> else <br/>{< br/> applicationinstance. processrequest (extradata); <br/> This. finishrequest (extradata. workerrequest, extradata, null); <br/>}< br/> catch (exception) <br/>{< br/> extradata. response. initresponsewriter (); <br/> This. finishrequest (WR, extradata, exception); <br/>}< br/>}
There are three key methods in httpapplicationfactory. getapplicationinstance:
Httpapplicationfactory. _ theapplicationfactory. ensureinited ();
Httpapplicationfactory. _ theapplicationfactory. ensureappstartcalled (context );
Httpapplicationfactory. _ theapplicationfactory. getnormalapplicationinstance (context );
1) httpapplicationfactory. _ theapplicationfactory. ensureinited ();
This method checks whether httpapplicationfactory is initialized. If not, it is initialized through httpapplicationfactory. INIT.
In Init (), obtain the complete path of the global. asax file, and then call compileapplication () to compile global. asax.
How is compilation performed?
Buildmanager completes compilation. Buildmanager first obtains globalasaxtype (that is, httpapplication), and then calls buildmanager. getglobalasaxbuildresult () = "getglobalasaxbuildresultinternal () =" ensuretoplevelfilescompiled () for compilation.
In ensuretoplevelfilescompiled, compile compilationstage. toplevelfiles to compile the files in the following three directories:
A. compileresourcesdirectory ();
Compile the app_globalresources directory.
B. compilewebrefdirectory ();
Compile the app_webreferences directory.
C. compilecodedirectories ();
Compile the app_code directory.
Compile compilationstage. globalasax and compile global. asax. method call: compileglobalasax () = applicationbuildprovider. getglobalasaxbuildresult (buildmanager. isprecompiledapp ).
The specific compilation in getglobalasaxbuildresult is completed by applicationbuildprovider and buildproviderscompiler.
Buildproviderscompiler. Compile mbuild.
Applicationbuildprovider. getbuildresult.
After compilation, a DLL file similar to app_global.asax.mlgx7n2v.dll is generated in the c: \ windows \ Microsoft. NET \ framework \ v2.0.50727 \ temporary ASP. NET files \ directory.
The compiled class named ASP. global_asax inherits from httpapplication.
Note: If the global. asax file does not exist in the web directory, files such as app_global.asax.mlgx7n2v.dll will not be compiled.
2) httpapplicationfactory. _ theapplicationfactory. ensureappstartcalled (context );
Create a specific httpapplication instance, trigger the applicationonstart event, and execute the application_start (Object sender, eventargs e) method in ASP. global_asax. The httpapplication instance created here is recycled after the event is processed.
3) httpapplicationfactory. _ theapplicationfactory. getnormalapplicationinstance (context );
This method creates an httpapplication instance and initializes it (call the system. Web. httpapplication. initinternal () method ).
Httpapplication instances are created based on the actual _ theapplicationtype. If the web directory does not contain the global. Asa file, that is, the ASP. global_asax type is not dynamically compiled, the httpapplication is directly instantiated. If the ASP. global_asax type is created, the ASP. global_asa is instantiated.
After an httpapplication instance is created, the initinternal method of the instance is called.
The initinternal method is also our key analysis method. The main functions of this method are as follows:
Internal void initinternal (httpcontext context, httpapplicationstate state, methodinfo [] handlers) <br/>{< br/> This. _ state = State; <br/> perfcounters. incrementcounter (appperfcounter. pipelines); <br/> This. _ initcontext = context; <br/> This. _ initcontext. applicationinstance = This; <br/> bool flag = false; <br/> urlmappingssection urlmappings = runtimeconfig. getappconfig (). urlmappings; <br/> flag = Urlmappings. isenabled & (urlmappings. urlmappings. count> 0); <br/> try <br/> {<br/> context. configurationpath = context. request. applicationpathobject; <br/> using (New httpcontextwrapper (context) <br/>{< br/> // depending on the web. and create the corresponding httpmodules. <Br/> This. initmodules (); <br/> // call the corresponding event processing function in the httpapplication instance based on the event. <Br/> If (handlers! = NULL) <br/>{< br/> This. hookupeventhandlersforappplicationandmodules (handlers); <br/>}< br/> This. _ context = context; <br/> This. _ hiderequestresponse = true; <br/> try <br/> {<br/> This. init (); <br/>}< br/> catch (exception) <br/>{< br/> This. recorderror (exception); <br/>}< br/> This. _ hiderequestresponse = false; <br/> This. _ context = NULL; <br/>/* creates many iexecutionstep interfaces. Class and add it to _ execsteps of the current httpapplication instance. <br/> * Wait for the callback to be executed. From this we can see that httpapplication processes Requests asynchronously. <br/> * many of the request processing work is implemented in _ execstep waiting for the callback to be executed. <Br/> */<br/> arraylist steps = new arraylist (); <br/> // checks the Request Path for security, disable unauthorized path access <br/> steps. add (New validatepathexecutionstep (this); <br/> // If urlmappings is set, perform rewritepath (urlmappingsexecutionstep ). <Br/> If (FLAG) <br/> {<br/> steps. add (New urlmappingsexecutionstep (this); <br/>}< br/> // execute event processing functions, such as beginrequest and authenticaterequest. <Br/> This. createeventexecutionsteps (eventbeginrequest, steps); <br/> This. createeventexecutionsteps (eventauthenticaterequest, steps); <br/> This. createeventexecutionsteps (eventdefaauthauthentication, steps); <br/> This. createeventexecutionsteps (eventpostauthenticaterequest, steps); <br/> This. createeventexecutionsteps (eventauthorizerequest, steps); <br/> This. createeventexecutionsteps (eventpostaut Horizerequest, steps); <br/> This. createeventexecutionsteps (eventresolverequestcache, steps); <br/> This. createeventexecutionsteps (eventpostresolverequestcache, steps); <br/> steps. add (New maphandlerexecutionstep (this); <br/> This. createeventexecutionsteps (eventpostmaprequesthandler, steps); <br/> This. createeventexecutionsteps (eventacquirerequeststate, steps); <br/> This. createeventexecutionstep S (eventpostacquirerequeststate, steps); <br/> This. createeventexecutionsteps (eventprerequesthandlerexecute, steps); <br/> steps. add (New callhandlerexecutionstep (this); <br/> This. createeventexecutionsteps (eventpostrequesthandlerexecute, steps); <br/> This. createeventexecutionsteps (eventreleaserequeststate, steps); <br/> This. createeventexecutionsteps (eventpostreleaserequeststate, steps); <br/> St EPS. add (New callfilterexecutionstep (this); <br/> This. createeventexecutionsteps (eventupdaterequestcache, steps); <br/> This. createeventexecutionsteps (eventpostupdaterequestcache, steps); <br/> This. _ endrequeststepindex = steps. count; <br/> This. createeventexecutionsteps (eventendrequest, steps); <br/> steps. add (New noopexecutionstep (); <br/> This. _ execsteps = new iexecutionstep [steps. count]; <br/> Steps. copyto (this. _ execsteps); <br/> This. _ resumestepswaitcallback = new waitcallback (this. resumestepswaitcallback); <br/>/* obtain the httphandler, Asp. NET page runtime compilation is also carried out here. (Maphandlerexecutionstep) <br/> * this process is performed by calling the system. Web. httpapplication. maphttphandler method. <Br/> * In maphttphandler, obtain the ihttphandlerfactory Implementation type from web. config Based on the access address. For Asp.net pages, <br/> * The default value is pagehanlderfactory. Create a pagehanlderfactory instance and call gethandlerhelper. <br/> * Call buildmanager in gethandlerhelper. createinstancefromvirtualpath: Compile and create the ASP.. NET page instance (if compiled, load it directly from the cache ). <Br/> * createinstancefromvirtualpath has been called several times. <br/> * The compilation task is assigned to buildmanager. compilewebfile (). Compilewebfile obtains the corresponding buildprovider from web. config. For the. aspx file, <br/> * the corresponding buildprovider is pagebuildprovider. How does pagebuildprovider compile pages? Further analysis is not performed here. If you are interested, you can further study the source code of ASP. NET 2.0. <Br/> * 5) Call The. processrequest method of the corresponding httphandler to process the request (if asynchronous, call beginprocessreques ). (Callhandlerexecutionstep) <br/> * 6) write the response content to the filter. (Callfilterexecutionstep) <br/> * 5. Call the beginprocessrequest of the httpapplication instance to process requests asynchronously. <Br/> * many of the events in _ execsteps mentioned above are executed after httpruntime calls httpapplication beginprocessrequest and calls resumesteps in beginprocessrequest. <Br/> */<br/>}< br/> finally <br/> {<br/> context. configurationpath = NULL; <br/> This. _ initcontext. applicationinstance = NULL; <br/> This. _ initcontext = NULL; <br/>}< br/> catch <br/>{< br/> throw; <br/>}< br/>}
Appendix: Application events