ASP.NET生命流程周期

我们上网时,在浏览器地址输入网址:Http://www.cnblogs.com,按下回车,一张网页就呈现在我们眼前。这究竟发生了什么?对于一名优秀的Programmer来说,我想有必要一下熟悉浏览器--->服务器请求的过程。

ASP.NET

ASP.NET是运行在公共语言运行时刻时 (CLR)上的应用程序框架。他用来在服务器端构建功能强大的web应用程序。当浏览器请求 ASP.NET 文件时,IIS 会把该请求传递给服务器上的 ASP.NET 引擎,ASP.NET 引擎会逐行地读取该文件,并执行文件中的脚本,最后,ASP.NET 文件会以纯 HTML 的形式返回浏览器。

客户端浏览器和服务器之间的请求响应是通过Socket进行通信,基于HTTP协议,客户端发送一次HTTP请求,服务器接收到请求,处理之后向浏览器回应响应报文。那么什么是HTTP协议呢?

HTTP协议:

当浏览器寻找到Web服务器地址后,浏览器将 帮助我们把对服务器的请求转换为一系列参数(消息)发给Web服务器,浏览器和Web服务器的对话中,需要使用双方都能理解语法规范进行通信,这种程序之 间进行通信的语法规定,我们称之为协议。浏览器与服务器之间的协议是应用层协议,当前遵循的协议是HTTP/1.1。HTTP/1.1协议时Web开发的 基础,这是一个无状态协议,客户端浏览器和服务器通过Socket通信进行请求和响应完成一次会话。每次会话中,通信双方发送的数据称为消息,分为两种: 请求消息和响应消息。

对于消息而言,一般他有三部分组成,并且消息的头和消息体之间用一个空行进行分隔:

ASP.NET生命流程周期_第1张图片

我们通过浏览器插件HttpWatch Professional可以清晰看到浏览器和服务器之间的通信内容:

ASP.NET生命流程周期_第2张图片

ASP.NET生命流程周期_第3张图片

了解了什么是HTTP协议之后,我们在回到先前提出的那个问题,浏览器的请求怎样到达服务器?

HTTP.SYS组件

我们知道要访问一个网站,必须要其部署在相应 服务器软件上(如IIS),浏览器向服务器发送请求之后,当请求通过Socket到达服务器时,首先服务器Windows内核中的HTTP.SYS组件捕 获请求,根据URL的请求地址将其转发到应用程序池(Application Pool,ASP.NET应用程序必须运行在一个应用程序池中),再由运行在应用程序池里的工作者进程(Worker Process,用于装载专门处理ASP.NET页面的一个ISAPI扩展程序:aspnet_isapi.dll)响应请求,当请求处理完成 时,HTTP.SYS又将结果发送出去(HTTP.SYS会在内部建立一个缓存区,用于缓存近期的处理结果)。当HTTP.SYS请求分析这是一个需要交 给IIS服务器处理的HTTP请求时,HTTP.SYS组件就会把这次请求交给IISl处理,服务器软件(IIS)会判断用户请求的是静态页面 (Html)还是动态页面(Aspx.Ashx),如果请求的是Html静态页面或者js,css,xml以及图片等,IIS直接返回请求的Html静态 页面和js等相应文件。那么如果请求的是动态页面呢?还是向处理静态页面一样吗?显然是不可能的。IIS服务器会分析请求的类型,然后从处理程序映射(即 下文IIS服务器扩展)表中去匹配,当在处理程序映射表中能够匹配到请求的类型时,那么IIS服务器就将请求交给处理程序映射表中所对应的程序来处理。当 IIS发现,在处理程序映射表中没有能匹配的项的时候,就直接返回请求所对应物理路径下的文件,如Html,JS,CSS,JPG,PNG等。

 

IIS服务器扩展

由于IIS服务器在设计时引入了开放的ISAPI接口标准,具备极高的可扩展性。在核心组件不变的情况下可灵活支持不同类型不同版本的ASP.NET应用程序。

ISAPI(Internet Server Application Programming Interface)

ISAPI(服务器应用编程接口),它为开发 人员提供了强大的可编程能力,只要按照标准接口开发不同类型的Web应用程序的ISAPI扩展程序,就能实现对IIS功能上的扩展,从而使IIS可以处理 不同类型的客户端请求。IIS管理器提供了应用程序配置功能,可以对不同的客户端请求配置不同的ISAPI扩展程序ISAPI扩展程序通常以DLL形式存 在,可以被IIS加载并调用。有了基于ISAPI的扩展扩展程序,IIS服务器就可以根据客户端请求的资源扩展名,来决定应由哪个ISAPI扩展程序来处 理客户端请求,然后就可以将请求转发给合适的ISAPI扩展程序。

IIS7处理程序映射

ASP.NET生命流程周期_第4张图片

ASP.NET生命流程周期_第5张图片

ASP.NET的后台辅助进程aspnet_wp.exe

实际上客户发起的请求最终要由 aspnet_isapi.dll(被工作者进程Worker Process装载)传递给aspnet_wp.exe去处理,.NET平台下称其为ASP.NET Process(简称为WP),该文件位于.Net Framework安装目录下,与aspnet_isapi.dll所在位置相同。当aspnet_isapi接收到IIS转发的ASP.NET请求后, 会将请求放入队列,并根据实际情况分配请求处理任务给WP进程。一旦请求被转送给WP进程,WP进程便会通知aspnet_isapi请求正在被处理。这 个通知的过程是通过同步I/O完成的,这么实现目的是为了保证处理过程的完整性,因为只有当请求在aspnet_isapi内部被标记 为"executing"后,WP才会真正开始处理该请求。此后请求便在WP的上下文环境中执行。当执行结束后处理结果会通过一个异步的开放管道回送给 aspnet_isapi,这时请求的状态会被更新为“Done”。接着请求就会从队列中清除。如果WP进程崩溃,所有正在处理中的请求都将维持 “executing”状态一段时间,等到aspnet_isapi检测到WP进程死掉后,会自动丢弃所有的请求并释放已经分配的资源。

WP会分析每一个请求的信息解析出其中的虚拟 目录信息,并检查该虚拟目录对应的AppDomain(应用程序域)是否已经存在,如果不存在,则创建一个新的 AppDomain(ApplicationManager创建应用程序域),然后使用它。否则直接重用已经建立的AppDomain对象。这里的 AppDomain指的是.NET中引入的应用程序域的概念,程序集管理的最小逻辑单位为应用程序域,包括四个重要的机制,隔离、卸载、安全、配置,它可 以理解为一个进程或一个边界或一个容器,它是应用程序的执行环境.NET下所有的应用程序都运行在AppDomain中,每一个ASP.NET应用程序 IIS中的站点或者虚拟目录都会有一个AppDomain与之对应,它保存了Applcation对象、Cache等全局变量。

由一张流程图回顾上述浏览器到达服务器的过程

ASP.NET生命流程周期_第6张图片

 
 
 ISAPIRuntme.ProcessRequest方法第一个进入ASP.NET
当aspnet_wp.exe接受到 aspnet_isapi.dll的请求后,就将请求转给指定虚拟目录对应的AppDomain中的ISAPIRuntime对 象,ISAPIRuntime.ProcessRequest()开始进入ASP.NET,并将浏览器发送请求消息封装成 HttpWorkerRequest类(抽象类,开发环境中对应SimpleWorkRequest)。接着执行StartProcessing方法,创 建HttpRuntime对象并调用其静态方法ProcessRequest。
 

 默默无闻的工作者对象HttpWorkerRequest

在Asp.Net中,准备用于处理的请求,必须封装为HttpWorkerRequest类型的对象,这是一个抽象类:
 
[ComVisibleAttribute(false)] public abstract class HttpWorkerRequest
 
客户的请求首先会被ISAPIRuntme对象ProcessRequest方法处理
创建了HttpWorkerRequest 类型的wr对象,因为ISAPIWorkerRequest 继承于HttpWorkerRequest

[SecurityPermission(SecurityAction.LinkDemand, Unrestricted=true)]
public int ProcessRequest(IntPtr ecb, int iWRType)
{
IntPtr zero = IntPtr.Zero;
......
ISAPIWorkerRequest wr = null;
try
{
bool useOOP = iWRType == 1;
wr = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);
wr.Initialize();
......
HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, SR.GetString("Hosting_Phys_Path_Changed", new object[] { appDomainAppPathInternal, appPathTranslated }));
return 1;
}


....
}

调用StartProcessing(),创建HttpRuntime对象并调用其静态方法:
[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] public static void ProcessRequest(HttpWorkerRequest wr) {     if (wr == null)     {         throw new ArgumentNullException("wr");     }     if (UseIntegratedPipeline)     {         throw new PlatformNotSupportedException(SR.GetString("Method_Not_Supported_By_Iis_Integrated_Mode", new object[] { "HttpRuntime.ProcessRequest" }));     }     ProcessRequestNoDemand(wr); } 
根据HttpWorkerRequest所提供的HTTP请求信息创建HttpContext对象。
点击进入ProcessRequsetNow(Wr)方法,Wr即封装了HTTP Message的HttpWorkRequest对象
在HttpRuntime接受到请求后,立刻通过HttpWorkerRequest传递的参数进行分析和分解,创建方便用户网站应用程序处理用的对象。HttpRequest,HttpResponse
终于发现了HttpContext
private void ProcessRequestInternal(HttpWorkerRequest wr) {     ......     else     {         HttpContext context;         try         {             context = new HttpContext(wr, false);         }         catch         {             try             {                 wr.SendStatus(400, "Bad Request");                 wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");                 byte[] data = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");                 wr.SendResponseFromMemory(data, data.Length);                 wr.FlushResponse(true);                 wr.EndOfRequest();                 return;             }             finally             {                 Interlocked.Decrement(ref this._activeRequestCount);             }         }         wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, context);         HostingEnvironment.IncrementBusyCount();         try         {             try             {                 this.EnsureFirstRequestInit(context);             }             catch             {                 if (!context.Request.IsDebuggingRequest)                 {                     throw;                 }             }    ......     } } 

 

在进入看看:

internal HttpContext(HttpWorkerRequest wr, bool initResponseWriter) {     this._timeoutStartTimeUtcTicks = -1;     this._timeoutTicks = -1;     this._threadAbortOnTimeout = true;     this.ThreadContextId = new object();     this._wr = wr;     this.Init(new HttpRequest(wr, this), new HttpResponse(wr, this));     if (initResponseWriter)     {         this._response.InitResponseWriter();     }     PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_EXECUTING); } 
 
 
 
private void ProcessRequestInternal(HttpWorkerRequest wr) {    ......       ......             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);             }         }        ...... } 

HttpApplicationFactotry用于负责管理一个HttpApplication的对象池。
看一下HttpApplication这个类的申明:

[ToolboxItem(false)]
public class HttpApplication : IComponent, IDisposable, IHttpAsyncHandler, IHttpHandler, IRequestCompletedNotifier, ISyncContext
{

}

HttpApplicationFactory.GetApplicationInstance(context);
GetApplicationInstance方法生成一个默认的HttpApplication对象,HttpApplication实现了IHttpHandler接口。
调用HttpApplication对象的GetNormalApplicationInstance
internal static IHttpHandler GetApplicationInstance(HttpContext context) {     if (_customApplication != null)     {         return _customApplication;     }     if (context.Request.IsDebuggingRequest)     {         return new HttpDebugHandler();     }     _theApplicationFactory.EnsureInited();     _theApplicationFactory.EnsureAppStartCalled(context);     return _theApplicationFactory.GetNormalApplicationInstance(context); } 
 

调用HttpApplication对象(它同时实现了IHttpAsyncHandler接口)的BeginProcessRequest方法执行客户请求。

if (applicationInstance is IHttpAsyncHandler)
{
IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;
context.AsyncAppHandler = handler2;
handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);
}

 

return _theApplicationFactory.GetNormalApplicationInstance(context);
再深入一步,进入GetNormalApplicationInstance方法之后,我们看到了HttpApplication对象是如何被创建和初始化:
private HttpApplication GetNormalApplicationInstance(HttpContext context) {     HttpApplication state = null;    ......     if (state == null)     {         state = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);         using (new ApplicationImpersonationContext())         {             state.InitInternal(context, this._state, this._eventHandlerMethods);         }     }     ......     return state; } 

我们发现HttpApplication类提供了一个名为InitInternal的方法,调用它来完成HttpApplication实例的初始化工作,点击进入InitInternal方法内部:

internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers) {     this._state = state;     PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);    ......                 this.InitModules();             Label_006B:                 if (handlers != null)                 {                     this.HookupEventHandlersForApplicationAndModules(handlers);                 }                 this._context = context;                 if (HttpRuntime.UseIntegratedPipeline && (this._context != null))                 {                     this._context.HideRequestResponse = true;                 }                 this._hideRequestResponse = true;                 try                 {                     this.Init();                 }                 catch (Exception exception)                 {                     this.RecordError(exception);                 }             }           ...... } 
 

初始化Modules,注册事件

private void InitModules() {     HttpModuleCollection modules = RuntimeConfig.GetAppConfig().HttpModules.CreateModules();     HttpModuleCollection other = this.CreateDynamicModules();     modules.AppendCollection(other);     this._moduleCollection = modules;     this.InitModulesCommon(); } 
    this._hideRequestResponse = false;     this._context = null;     this._resumeStepsWaitCallback = new WaitCallback(this.ResumeStepsWaitCallback);     if (HttpRuntime.UseIntegratedPipeline)     {       this._stepManager = new PipelineStepManager(this);     }     else     {        this._stepManager = new ApplicationStepManager(this);     }     this._stepManager.BuildSteps(this._resumeStepsWaitCallback);           
 

可以看到在HttpApplication对 象初始化时,首先会调用InitModules方法来加载在web.config文件中配置的所有HttpModule模块。接着 HookupEventHandlersForApplicationAndModules方法被调用,这个方法完成global.asax文件中配置的 HttpModule或HttpApplication事件的绑定

最后ApplicationStopManager对象的BuildSteps方法被调用,完成HttpApplication事件的绑定。这个方法很重要,它将创建各种HttpApplication.IExecutionStep保存
到一个数组列表,以便在BeginProcessRequest方法内部调用ResumeSteps方法依次执行这些对象的Execute()方法,完成各种处置。

internal override void BuildSteps(WaitCallback stepCallback) {     ArrayList steps = new ArrayList();     HttpApplication app = base._application;     bool flag = false;     UrlMappingsSection urlMappings = RuntimeConfig.GetConfig().UrlMappings;     flag = urlMappings.IsEnabled && (urlMappings.UrlMappings.Count > 0);     steps.Add(new HttpApplication.ValidateRequestExecutionStep(app));     steps.Add(new HttpApplication.ValidatePathExecutionStep(app));     if (flag)     {         steps.Add(new HttpApplication.UrlMappingsExecutionStep(app));     }     app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);//将事件加入steps     app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);     app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);     app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);     app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);     app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);     app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);     app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);     steps.Add(new HttpApplication.MapHandlerExecutionStep(app));     app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);     app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);     app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);     app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);     steps.Add(app.CreateImplicitAsyncPreloadExecutionStep());     steps.Add(new HttpApplication.CallHandlerExecutionStep(app));     app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);     app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);     app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);     steps.Add(new HttpApplication.CallFilterExecutionStep(app));     app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);     app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);     this._endRequestStepIndex = steps.Count;     app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps);     steps.Add(new HttpApplication.NoopExecutionStep());     this._execSteps = new HttpApplication.IExecutionStep[steps.Count];     steps.CopyTo(this._execSteps);     this._resumeStepsWaitCallback = stepCallback; } 
 
private void CreateEventExecutionSteps(object eventIndex, ArrayList steps) {     AsyncAppEventHandler handler = this.AsyncEvents[eventIndex];     if (handler != null)     {         handler.CreateExecutionSteps(this, steps);     }     EventHandler handler2 = (EventHandler) this.Events[eventIndex];     if (handler2 != null)     {         Delegate[] invocationList = handler2.GetInvocationList();         for (int i = 0; i < invocationList.Length; i++)         {             steps.Add(new SyncEventExecutionStep(this, (EventHandler) invocationList[i]));         }     } } 
 

this._execSteps = new HttpApplication.IExecutionStep[steps.Count]; steps.CopyTo(this._execSteps); this._resumeStepsWaitCallback = stepCallback;//重要

IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {     this._context = context;     this._context.ApplicationInstance = this;     this._stepManager.InitRequest();     this._context.Root();     HttpAsyncResult result = new HttpAsyncResult(cb, extraData);     this.AsyncResult = result;     if (this._context.TraceIsEnabled)     {         HttpRuntime.Profile.StartRequest(this._context);     }     this.ResumeSteps(null);     return result; } 

 在取得HttpApplication对象 实例之后HttpRuntime对象开始调用其的BeginProcessRequest方法来实现IHttpAsyncHandler接口中定义的方法 处理请求:该方法首先调用ApplicationStepManager对象的InitRequest方法完成一些初始化工作例如将记录当前执行步骤的变 量清0、置请求处理完成标志为false等。然后根据上下文创建HttpAsyncResult对象记录执行结果最后ResumeSteps方法被调用这 个方法会依次取出在数组列表中的HttpApplication.IExecutionStep对象传递给HttpApplication的 ExecuteStep方法由它调用执行IExecutionStep对象的Execute方法。当执行到 MapHandlerExecutionStep时会执行如下代码获取最终执行请求的HttpHandler context.Handler this._application.MapHttpHandlercontext request.RequestType request.FilePathObject request.PhysicalPathInternal false HttpApplication对象的MapHttpHandler方法将根据配置文件结合请求类型和URL以调用相应的 IHttpHandlerFactory来获取HttpHandler对象例如与.aspx页面对应的Page类就是一种HttpHandler。此后请 求处理的执行权被转交至对应的HttpHandler对象上。

internal class MapHandlerExecutionStep : HttpApplication.IExecutionStep {     // Fields     private HttpApplication _application;      // Methods     [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]     internal MapHandlerExecutionStep(HttpApplication app)     {         this._application = app;     }      void HttpApplication.IExecutionStep.Execute()     {         HttpContext context = this._application.Context;         HttpRequest request = context.Request;       ......         context.Handler = this._application.MapHttpHandler(context, request.RequestType, request.FilePathObject, request.PhysicalPathInternal, false);      ......     }      // Properties ...... } 


HttpApplication的19个事件:

ASP.NET生命流程周期_第7张图片

19个事件的处理过程:

  • 在Asp.Net 中,Asp.Net服务器对于每一次请求的处理过程是相同的,都要经过HttpApplication处理管道,管道内部的处理过程是固定的,在服务器处 理请求的各个阶段,伴随着处理的进行,一次触发对应的事件,以便程序员在处理的各个阶段完成自定义的处理工作。
  • 首先触发的事件是BeginRequest,这个事件标志着ASP.NET服务器处理工作的开始,也是程序员在ASP.NET中针对请求能够处理的第一个事件。
  • 开始处理请求后,第一个重 要的工作就是确定请求用户的身份以及实现安全机制。这个工作通过AuthenticateRequest和 PostAuthenticateRequest两个事件提供检查当前请求用户身份的机会。PostAuthenticateRequest则表示用户身 份已经检查完成,检查后的用户可以通过HttpContext的User属性获取列。
public IPrincipal User {     get     {         return this._principalContainer.Principal;     }     [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries"), SecurityPermission(SecurityAction.Demand, ControlPrincipal=true)]     set     {         this.SetPrincipalNoDemand(value);     } }

 Iprincipal又有一个名为Identity,类型了System.Security.Principal.IIdentity属性
[ComVisible(true), __DynamicallyInvokable] public interface IPrincipal {     // Methods     [__DynamicallyInvokable]     bool IsInRole(string role);      // Properties     [__DynamicallyInvokable]     IIdentity Identity { [__DynamicallyInvokable] get; } } 
 
IsAuthenticated表示当前请求用户是否已经被验证,IsAuthenticated =false,那么表示这是一个匿名用户,如果为True,那么通过IIdentity类型为string的Name属性,
这就表示当前请求的用户名。
[ComVisible(true), __DynamicallyInvokable] public interface IIdentity {     // Properties     [__DynamicallyInvokable]     string AuthenticationType { [__DynamicallyInvokable] get; }     [__DynamicallyInvokable]     bool IsAuthenticated { [__DynamicallyInvokable] get; }     [__DynamicallyInvokable]     string Name { [__DynamicallyInvokable] get; } } 

 

 

  • 当ASP.NET获取用户 身份后,根据当前请求的用户身份,开始请求权限的检查工作。当第四个事件AuthorizeRequest触发的时候开始进行用户的权限检查,而第五个事 件PostAuthorizeRequest则标志已经完成用户权限检查工作。如果用户没有通过安检,一般情况下将跳过剩余事件,直接触发 EndRequest事件结束处理请求过程。

 

  • 当用户获取了请求权限,那 么服务器开始准备用最快的方式来使用户得到回应结果。ResolveRequestCache事件标志着到从前缓存的结果进行检查,看看是否可以直接从以 前的缓存结果中直接获取处理结果,PostResolveRequestCache表示缓存检查结束。

 

  • 当不能从缓存中获取结果 时,必须通过一次处理来计算出当前请求的结果。在ASP.NET中,用户处理请求以得到结果的对象称为处理程序Handler。为了处理这个这个请 求,ASP.NET必须按照匹配规则找到一个处理当前请求的处理程序,PostMapRequestHandler事件表示当前ASP.NET已经获取了 这个处理程序,HttpContext的Handler属性就表示这个处理程序对象。

 

  • 得到了处理程序之后,还不 能马上开始进行处理,这是由于处理请求还需要与这个请求有关的数据,比如说这个用户上一次向服务器发送请求的时候,在服务器上报错了一些这个用户特有的数 据。由于HTTP协议的无状态性,状态管理问题是个核心问题,所以ASP时代就引入Session,提供基于会话状态的管理。为了获取这个用户在以前保存 的数据,通过AcquireRequestState事件取得请求状态,PostAcquireRequest事件则表示已经完成了用户数据的获取工作, 可以再处理中使用了。
  • PreRequestHandlerExcute 事件用来通知程序员,处理程序就要开始进行处理工作了,如果用户的状态已经获取之后,还有需要的处理程序之进行的工作,那么就在这个事件中处理吧。在 PreRequestHandlerExcute事件之后,ASP.NET服务器将通过执行处理程序完成请求处理工作。这个处理程序有可能是一个 WebForm,也可能是Web服务。这个工作是在第11个事件和第12个事件之间完成的。

 

  • 处理程序之后,服务器开始进行扫尾工作,PostRequestHandlerExcute事件通知程序员,ASP.NET服务器处理程序已经完成。
  • 在处理完成之后,由于处理 程中,用户可能修改了用于特定的专属数据,那么修改之后的用户状态数据需要进行序列化或者进行保存处理。ReleaseRequestState事件通知 程序员需要释放这些状态数据,PostReleaseRequestState则表示已经释放完成。

 

  • 在处理完成之后,如果需要将这次处理结果缓存起来,以便于后继的请求可以直接使用这个结果,UpdateRequestCache事件提供了处理的机会,PostUpdateRequestCache则表示缓存已经更新完毕。
  • 在ASP.NET4.0中,新增加了两个事件完成处理的日志工作:LogRequest表示将这次请求加入日志,PostLogRequest表示完成了日志工作。
  • 在前面的事件中,请求并不 一定要经过所有的事件,比如说,用户没用经过授权的检查,那么将跳过后面的事件,但是,EndRequest事件是所有请求都要经过的最后一个 HttpApplication处理管道的事件,也是程序员处理的ASP.NET处理请求中的最后一个机会。这个事件之后,处理的结果将被回应到浏览器, 完成ASP.NET服务器的处理工作。

 小结

你可能感兴趣的:(asp.net)