ASP. NET Process Model II: ASP. NET Http Runtime Pipeline-Part

Source: Internet
Author: User

Ii. ASP. NET Runtime Pipeline (Continued ASP. NET Http Runtime Pipeline-Part I)

Now we are actually going to ASP. the scope of the NET jurisdiction covers basically The objects involved in the entire processing process. Next we will discuss how these objects work together to process Http requests, and finally generate the Http Response we need.

 

HttpContext

The above section describes how to pass the corresponding isapi ecb Pointer to the ProcessRequest method when ISAPI calls ISAPIRuntime, this ECB pointer can be seen as the only channel for data exchange in a hosted and unmanaged environment. Server Variable and Request Parameter Pass in ASP through it. NET as the basis for further processing, ASP. the last Response generated by NET is passed to the ISAPI through it, and is further passed to IIS and finally returned to the Client.

With this passed-in ECB Pointer, we have created an ISAPIWorkerRequest. ISAPIWorkerRequest is used as a parameter to pass in the call of HttpRuntime. ProcessRequestNoDemand. HttpRuntime. ProcessRequestNoDemand is ultimately reflected in calling ProcessRequestInternal. The following is the implementation of a real method:

 

ProcessRequestInternal
Private void ProcessRequestInternal (HttpWorkerRequest wr)
{
HttpContext context;
Try
{
Context = new HttpContext (wr, false );
}
Catch
{
Wr. SendStatus (400, "Bad Request ");
Wr. SendKnownResponseHeader (12, "text/html; charset = UTF-8 ");
Byte [] bytes = Encoding. ASCII. GetBytes ("Wr. SendResponseFromMemory (bytes, bytes. Length );
Wr. FlushResponse (true );
Wr. EndOfRequest ();
Return;
}
Wr. SetEndOfSendNotification (this. _ asyncEndOfSendCallback, context );
Interlocked. Increment (ref this. _ activeRequestCount );
HostingEnvironment. IncrementBusyCount ();
Try
{
Try
{
This. EnsureFirstRequestInit (context );
}
Catch
{
If (! Context. Request. IsDebuggingRequest)
{
Throw;
}
}
Context. Response. InitResponseWriter ();
IHttpHandler applicationInstance = HttpApplicationFactory. GetApplicationInstance (context );
If (applicationInstance = null)
{
Throw new HttpException (SR. GetString ("Unable_create_app_object "));
}
If (EtwTrace. IsTraceEnabled (5, 1 ))
{
EtwTrace. Trace (EtwTraceType. ETW_TYPE_START_HANDLER, context. WorkerRequest, applicationInstance. GetType (). FullName, "Start ");
}
If (applicationInstance is IHttpAsyncHandler)
{
IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;
Context. AsyncAppHandler = handler2;
Handler2.BeginProcessRequest (context, this. _ handlerCompletionCallback, context );
}
Else
{
ApplicationInstance. ProcessRequest (context );
This. FinishRequest (context. WorkerRequest, context, null );
}
}
Catch (Exception exception)
{
Context. Response. InitResponseWriter ();
This. FinishRequest (wr, context, exception );
}
}

There is no need to go into the code above the object. We only need to understand the general execution process. The following pseudo code basically reflects the entire execution process:


HttpContext context = new HttpContext (wr, false );
IHttpHandler applicationInstance = HttpApplicationFactory. GetApplicationInstance (context );

First, create an HttpContext object through the created ISAPIWorkerRequest, and then create an IHttpHandler object through HttpApplicationFactory. GetApplicationInstance (generally an HttpApplication object ).

As his name implies, HttpContext indicates the context information of the current Request, and its lifecycle indicates that the entire Request processing is completed or the processing times out. Through the HttpContext object, we can access a series of common objects belonging to the current Request: Server, Session, Cache, Application, Request, Response, Trace, User, Profile, and so on. In addition, we can think that some data is put in the Items attribute as a way of State management, but this kind of state management and other common methods, such as Session, Cache, Application, Cookie, etc, the fundamental difference is that the lifecycle is only maintained in the Context of the current Request.

2. HttpApplication

Just like its name, HttpApplication can basically be seen as an embodiment of ASP. NET Application. HttpApplication corresponds to Gloabal. asax in the virtual root directory. Create an HttpApplication object based on Gloabal. asax through HttpApplicationFactory. GetApplicationInstance. In HttpApplicationFactory. before the GetApplicationInstance method returns the created HttpApplication object, an internal method named InitInternal is called. This method initializes some columns. In these initialization operations, the most typical initialization method is InitModules (). The main purpose of this method is to view all the httpmodules registered in Config and load the corresponding Assembly according to the configuration information, create the corresponding HttpModule through Reflection and add these modules to the _ moduleCollection Filed of HttpApplication.

HttpApplication itself contains any processing of the Request. It works by starting different events at different stages to call the Event Hander we registered.

All events of HttpApplication are listed below and arranged in sequence according to the trigger time:

BeginRequest:
AuthenticateRequest & Post AuthenticateRequest
AuthorizeRequest & Post AuthorizeRequest
ResolveRequestCache & Post ResolveRequestCache
PostMapRequestHandler:
AcquireRequestState & AcquireRequestState:
PreRequestHandlerExecute & Post RequestHandlerExecute:
ReleaseRequestState & Post ReleaseRequestState
UpdateRequestCache & PostUpdateRequestCache
EndRequest:
ASP. NET Application, AppDomain and HttpApplication

For an ASP. NET Application, an Application corresponds to a virtual directory. Does an Application correspond to an AppDomain? Does an Application correspond to a unique Httpapplication object? The answer is no.

First, let's take a look at the relationship between the Application and HttpApplication, although our Request to an Application is ultimately carried by an HttpApplication object. But it cannot be said that an Application only corresponds to a fixed HttpApplication object. The reason is simple, ASP. NET is inherently multithreaded and needs to be accessed through different clients. If we only use one HttpApplication to process these concurrent requests, it will have a serious impact on Responsibility, ASP. NET uses the Pool mechanism for HttpApplication: When the Request arrives, ASP. NET searches for unused HttpApplication objects in the HttpApplication Pool. If not, it is created. Otherwise, it is extracted directly from the Pool. The HttpApplication object processed by the Request will not be destroyed immediately, but will be put back to the Pool for the next Request to use.

For the relationship between Application and AppDomain, you may say that an Application must only run in one AppDomain. In general, this sentence is understandable, but it ignores a special scenario: when the current Application is processing the Request, we put the web. config and other related files have been modified, and such changes can be immediately modified by ASP. NET detected, in order to make our changes take effect in a timely manner, for the first Request after the change, ASP. NET will create a new AppDomain for a period of time, and for the original AppDomain, it may still be processing the Request before the modification, all the original Appdomain will continue until the processing of the original Request ends, therefore, for an Application, multiple AppDomains may coexist.

3. HttpModule

As mentioned above, HttpApplication is an embodiment of ASP. NET Application. HttpApplication itself does not provide the Request processing function, but starts different events at different stages. What we can do is to register our function code as Event Handler to the required HttpApplication Event according to our specific needs. To register these Event Handler, we must first define our EventHandler in Global. asax corresponding to HttpApplication. This is the most direct method, and Global. asax provides a simple way to achieve simple implementation: you do not need to add Delegate to the corresponding Event like registering an Event, instead, the corresponding method is directly used as the relevant Event Handler by matching the method name and the corresponding Event. For example, the Application _ AcquireRequestState is the AcquireRequestState Event handler.

However, this method does not meet our requirements in many cases. More importantly, we need a Plug-in implementation method: We define some external Request Processing functions, it needs to be applied directly to our Application. By using HttpModule to encapsulate these functional modules and registering them to our Application, you can easily implement this function.

HttpModule implements the System. Web. IHttpModule interface, which is simple and has only two members:


[AspNetHostingPermission (SecurityAction. InheritanceDemand, Level = AspNetHostingPermissionLevel. Minimal), AspNetHostingPermission (SecurityAction. LinkDemand, Level = AspNetHostingPermissionLevel. Minimal)]
Public interface IHttpModule
{
// Methods
Void Dispose ();
Void Init (HttpApplication context );
}

We only need to register the corresponding HttpApplication Event Handler in the Init method:

 

Public class BasicAuthCustomModule: IHttpModule
{
Public void Init (HttpApplication application)
{
Application. AuthenticateRequest + =
New EventHandler (this. OnAuthenticateRequest );
}
Public void Dispose (){}
 
Public void OnAuthenticateRequest (object source, EventArgs eventArgs)
{

}
}

All httpModules are defined in the same way as the httpModules Section of machine. config or Web. config. Below are all httpModules defined in Machine. config.

 

<HttpModules>
<Add name = "OutputCache" type = "System. Web. Caching. OutputCacheModule"/>
<Add name = "Session" type = "System. Web. SessionState. SessionStateModule"/>
<Add name = "WindowsAuthentication" type = "System. Web. Security. WindowsAuthenticationModule"/>
<Add name = "FormsAuthentication" type = "System. Web. Security. FormsAuthenticationModule"/>
<Add name = "PassportAuthentication" type = "System. Web. Security. PassportAuthenticationModule"/>
<Add name = "UrlAuthorization" type = "System. Web. Security. UrlAuthorizationModule"/>
<Add name = "FileAuthorization" type = "System. Web. Security. FileAuthorizationModule"/>
<Add name = "ErrorHandlerModule" type = "System. Web. Mobile. ErrorHandlerModule, System. Web. Mobile, Version = 1.0.5000.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a"/>
</HttpModules>

But how does HttpModule work? Let's review the previous section: HttpApplicationFactory. before the GetApplicationInstance method returns the created HttpApplication object, an internal method named InitInternal is called. This method initializes some columns. In these initialization operations, the most typical initialization method is InitModules (). The main purpose of this method is to view all the httpmodules registered in Config and load the corresponding Assembly according to the configuration information, create the corresponding HttpModule through Reflection, add these modules to _ moduleCollection Filed of HttpApplication, and call the Init method of each HttpModule in sequence. The implementation is as follows:


Private void InitModules ()
{
This. _ moduleCollection = RuntimeConfig. GetAppConfig (). HttpModules. CreateModules ();
This. InitModulesCommon ();
}


Private void InitModulesCommon ()
{
Int count = this. _ moduleCollection. Count;
For (int I = 0; I <count; I ++)
{
This. _ currentModuleCollectionKey = this. _ moduleCollection. GetKey (I );
This. _ moduleCollection [I]. Init (this );
}
This. _ currentModuleCollectionKey = null;
This. InitAppLevelCulture ();
}

HttpHandler

If HttpModule is concerned with the processing of all Inbound requests, Handler does focus on requests based on some type of ASP. NET Resource. For example, A. apsx Web Page is processed through a System. Web. UI. Page. HttpHandler and the resources it processes are defined through the system. web/handlers section in Config. The following is the definition in Machine. config.

<HttpHandlers>
<Add verb = "*" path = "trace. axd" type = "System. Web. Handlers. TraceHandler"/>
<Add verb = "*" path = "*. aspx" type = "System. Web. UI. PageHandlerFactory"/>
<Add verb = "*" path = "*. ashx" type = "System. Web. UI. SimpleHandlerFactory"/>
<Add verb = "*" path = "*. asmx "type =" System. web. services. protocols. webServiceHandlerFactory, System. web. services, Version = 1.0.5000.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a "validate =" false "/>
<Add verb = "*" path = "*. rem "type =" System. runtime. remoting. channels. http. httpRemotingHandlerFactory, System. runtime. remoting, Version = 1.0.5000.0, Culture = neutral, PublicKeyToken = b77a5c561934e089 "validate =" false "/>
<Add verb = "*" path = "*. soap "type =" System. runtime. remoting. channels. http. httpRemotingHandlerFactory, System. runtime. remoting, Version = 1.0.5000.0, Culture = neutral, PublicKeyToken = b77a5c561934e089 "validate =" false "/>
<Add verb = "*" path = "*. asax" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. ascx" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "GET, HEAD" path = "*. dll. config" type = "System. Web. StaticFileHandler"/>
<Add verb = "GET, HEAD" path = "*. exe. config" type = "System. Web. StaticFileHandler"/>
<Add verb = "*" path = "*. config" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. cs" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. csproj" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. vb" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. vbproj" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. webinfo" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. asp" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. licx" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. resx" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "*" path = "*. resources" type = "System. Web. HttpForbiddenHandler"/>
<Add verb = "GET, HEAD" path = "*" type = "System. Web. StaticFileHandler"/>
<Add verb = "*" path = "*" type = "System. Web. HttpMethodNotAllowedHandler"/>
</HttpHandlers>

Note that we can not only define a Type that implements System. Web. IHttpHandler, but also define a Type that implements System. Web. IHttpHandlerFactory. System. Web. UI. Page is a typical Httphandler. I believe you are familiar with it. Finally, let's talk about another typical HttpHandler: System. web. httpForbiddenHandler, we can see from the name that it is used for those resources that are not allowed to access, now we should know that for Global. asax is accessed through IIS.

Reference:
A low-level Look at the ASP. NET Architecture

 

Author: Artech

Related 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.