zoukankan      html  css  js  c++  java
  • 【转】ASP.NET页面请求管道流程

    [转]http://blog.csdn.net/tycyd/article/details/3755708

    当客户端向web服务器请求*.aspx的页面文件时,这个http请求也会被inetinfo.exe进程截获(www服务),它判断文件后缀之后,把这个请求转交给ASPNET_ISAPI.DLL而ASPNET_ISAPI.DLL则会通过一个Http PipeLine的管道,将这个http请求发送给ASPNET_WP.EXE进程,当这个HTTP请求进入ASPNET_WP.EXE进程之后,asp.net framework就会通过HttpRuntime来处理这个Http请求,处理完毕后将结果返回给客户端。
    
    大致流程如下:
    HttpRequest-->inetinfo.exe->ASPNET_ISAPI.DLL-->Http Pipeline-->ASPNET_WP.EXE-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()
    
    通过反编译器,我们来简单看看它是如何实现的(.Net Version=2.0.0.0)
    工作进程(IIS5中是ASPNET_WP.EXE,IIS6中是W3WP.EXE)寄宿.NET运行时和ISAPI DLL,它(工作进程)通过调用COM对象的一个小的非托管接口最终将调用发送到ISAPIRuntime类的一个实例上。进入运行时的第一个入口就是这个没有被文档记载的类,这个类实现了IISAPIRuntime接口(对于调用者说明来说,这个接口是一个COM接口)这个基于Iunknown的底层 COM接口是从ISAPI扩展到ASP.NET的一个预定的接口
    
       1. [ComImport, Guid("08a2c56f-7c16-41c1-a8be-432917a1a2d1"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
       2. public interface IISAPIRuntime
       3. {
       4.     void StartProcessing();
       5.     void StopProcessing();
       6.     [return: MarshalAs(UnmanagedType.I4)]
       7.     int ProcessRequest([In] IntPtr ecb, [In, MarshalAs(UnmanagedType.I4)] int useProcessModel);
       8.     void DoGCCollect();
       9. }
    
    代码展示了IISAPIRuntime接口和它的调用签名代码
    
    以下是ISAPIRuntime类
    
       1. public sealed class ISAPIRuntime : MarshalByRefObject, IISAPIRuntime, IRegisteredObject
       2. {
       3.     // Fields
       4.     private static int _isThisAppDomainRemovedFromUnmanagedTable;
       5.     private static string s_thisAppDomainsIsapiAppId;
       6.     private const int WORKER_REQUEST_TYPE_IN_PROC = 0;
       7.     private const int WORKER_REQUEST_TYPE_IN_PROC_VERSION_2 = 2;
       8.     private const int WORKER_REQUEST_TYPE_OOP = 1;
       9.
      10.     // Methods
      11.     [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Minimal), SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
      12.     public ISAPIRuntime();
      13.     public void DoGCCollect();
      14.     public override object InitializeLifetimeService();
      15.     public int ProcessRequest(IntPtr ecb, int iWRType);
      16.     internal static void RemoveThisAppDomainFromUnmanagedTable();
      17.     internal void SetThisAppDomainsIsapiAppId(string appId);
      18.     public void StartProcessing();
      19.     public void StopProcessing();
      20.     void IRegisteredObject.Stop(bool immediate);
      21. }
    
    我们知道了接口,那具体处理,就让我们看一下ISAPIRuntime.ProcessRequest函数
    
       1. public int ProcessRequest(IntPtr ecb, int iWRType)
       2. {
       3.     。。。。。。
       4.     。。。。。。
       5.     ISAPIWorkerRequest wr = null;
       6.     try
       7.     {
       8.          。。。。。。
       9.         wr = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);
      10.         wr.Initialize();
      11.         string appPathTranslated = wr.GetAppPathTranslated();
      12.         string appDomainAppPathInternal = HttpRuntime.AppDomainAppPathInternal;
      13.         if ((appDomainAppPathInternal == null) || StringUtil.EqualsIgnoreCase(appPathTranslated, appDomainAppPathInternal))
      14.         {
      15.             HttpRuntime.ProcessRequestNoDemand(wr);
      16.             return 0;
      17.         }
      18.         。。。。
      19.         return 1;
      20.     }
      21.     catch (Exception exception)
      22.     {
      23.        。。。。
      24.     }
      25. }
      26.
    27.
    
    在这个函数中首先创建了一个ISAPIWorkerRequest实例,即是被.Net`经过一层封装的Http请求,
    随后继续调用HttpRuntime.ProcessRequestNoDemand(wr);进行处理
    
       1. internal static void ProcessRequestNoDemand(HttpWorkerRequest wr)
       2. {
       3.     RequestQueue queue = _theRuntime._requestQueue;
       4.     if (queue != null)
       5.     {
       6.         wr = queue.GetRequestToExecute(wr);
       7.     }
       8.     if (wr != null)
       9.     {
      10.         。。。。
      11.         。。。。
      12.         ProcessRequestNow(wr);
      13.     }
      14. }
    
    如果请求有多个,则进行请求队列的筛选,取得要处理的请求,继续转交ProcessRequestNow(wr)处理
    
       1. internal static void ProcessRequestNow(HttpWorkerRequest wr)
       2. {
       3.     _theRuntime.ProcessRequestInternal(wr);
       4. }
    
    调用当前应用程序域的方法_theRuntime.ProcessRequestInternal(wr)
    
       1. private void ProcessRequestInternal(HttpWorkerRequest wr)
       2. {
       3.     HttpContext context;
       4.     try
       5.     {
       6.         context = new HttpContext(wr, false);
       7.     }
       8.     catch
       9.     {
      10.         wr.SendStatus(400, "Bad Request");
      11.         ..........
      12.         return;
      13.     }
      14.     .........
      15.     try
      16.     {
      17.         ........
      18.         context.Response.InitResponseWriter();
      19.         IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);
      20.         if (applicationInstance == null)
      21.         {
      22.             throw new HttpException(SR.GetString("Unable_create_app_object"));
      23.         }
      24.         ........
      25.         if (applicationInstance is IHttpAsyncHandler)
      26.         {
      27.             IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;
      28.             context.AsyncAppHandler = handler2;
      29.             handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);
      30.         }
      31.         else
      32.         {
      33.             applicationInstance.ProcessRequest(context);
      34.             this.FinishRequest(context.WorkerRequest, context, null);
      35.         }
      36.     }
      37.     catch (Exception exception)
      38.     {
      39.         .........
      40.     }
      41. }
    
    在这个方法内主要完成了
    1.HttpContext的创建(非常重要的实例,提供了绝大多数的接口)
    2.通过HttpApplicationFactory.GetApplicationInstance(context)生成或回收HttpApplicaiton实例(确切地说实现IHttpAsyncHandler接口或者IHttpHandler接口的实例),并转交请求处理
    handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);
    或者applicationInstance.ProcessRequest(context);
    其中,HttpApplicationFactory.GetApplicationInstance(context),若Http请求是第一个到达的时候,将会初始化HttpApplicationFactory
    
       1. internal static IHttpHandler GetApplicationInstance(HttpContext context)
       2. {
       3.     。。。。。。。。。。。
       4.     _theApplicationFactory.EnsureInited();
       5.     _theApplicationFactory.EnsureAppStartCalled(context);
       6.     return _theApplicationFactory.GetNormalApplicationInstance(context);
       7. }
       8.
    
    _theApplicationFactory.EnsureInited();中将判断工厂是否被初始化,若没则会先进行ApplicationFactory初始化
    _theApplicationFactory.EnsureAppStartCalled(context);创建特定的HttpApplication实例,触发ApplicationOnStart事件,执行ASP.global_asax中的 Application_Start(object sender, EventArgs e)方法。这里创建的HttpApplication实例在处理完事件后,就被回收。
    
    ApplicationFactory初始化最终调用Init() 方法
    
       1. private void Init()
       2. {
       3.     if (_customApplication == null)
       4.     {
       5.         try
       6.         {
       7.             try
       8.             {
       9.                 this._appFilename = GetApplicationFile();
      10.                 this.CompileApplication();
      11.             }
      12.             。。。。。
      13.         }
      14.         catch
      15.         {
      16.             throw;
      17.         }
      18.     }
      19. }
      20.  
    21.
    
    this._appFilename = GetApplicationFile();取得global.asax文件路径
    
       1. internal static string GetApplicationFile()
       2. {
       3.     return Path.Combine(HttpRuntime.AppDomainAppPathInternal, "global.asax");
       4. }
    
    可见在.Net中global.asax文件名是被规定死的。
    this.CompileApplication也是比较重要的
    
       1. private void CompileApplication()
       2. {
       3.     this._theApplicationType = BuildManager.GetGlobalAsaxType();
       4.     BuildResultCompiledGlobalAsaxType globalAsaxBuildResult = BuildManager.GetGlobalAsaxBuildResult();
       5.     if (globalAsaxBuildResult != null)
       6.     {
       7.         if (globalAsaxBuildResult.HasAppOrSessionObjects)
       8.         {
       9.             this.GetAppStateByParsingGlobalAsax();
      10.         }
      11.         this._fileDependencies = globalAsaxBuildResult.VirtualPathDependencies;
      12.     }
      13.     if (this._state == null)
      14.     {
      15.         this._state = new HttpApplicationState();
      16.     }
      17.     this.ReflectOnApplicationType();
      18. }
      19.
    20.
    
    this._theApplicationType = BuildManager.GetGlobalAsaxType();
    若存在global.asax文件则返回与该文件绑定编译的类型
    若不存在则返回HttpApplication类型
    05至12的代码则是在存在global.asax文件的情况下,生成文件解分器,应用程序状态就从其中被创建(HttpApplicationState)。
    13至16,在不存在global.asax文件的情况下,创建默认HttpApplicationState;
    在这里可以看到应用程序状态HttpApplicationState实例其实是HttpApplicationFactory的成员变量,所以其生存周期是整个应用程序域,作用域则是可被所有客户端应用程序(HttpApplication)共享。
    
    this.ReflectOnApplicationType();通过映射theApplicationType,保存theApplicationType中的函数信息(用于之后HttpApplication实例事件函数输出),但是有三个函数是特别的,他们属于HttpApplicationFactory级别,就是应用程序域级别的事件函数输出,它们是Application_OnStart,Application_OnEnd,Session_OnEnd。
    首先看一下ReflectOnApplicationType函数
    
       1. private void ReflectOnApplicationType()
       2. {
       3.     ArrayList list = new ArrayList();
       4.     foreach (MethodInfo info in this._theApplicationType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance))
       5.     {
       6.         if (this.ReflectOnMethodInfoIfItLooksLikeEventHandler(info))
       7.         {
       8.             list.Add(info);
       9.         }
      10.     }
      11.     Type baseType = this._theApplicationType.BaseType;
      12.     if ((baseType != null) && (baseType != typeof(HttpApplication)))
      13.     {
      14.        。。。。。。
      15.     }
      16.     this._eventHandlerMethods = new MethodInfo[list.Count];
      17.     for (int i = 0; i < this._eventHandlerMethods.Length; i++)
      18.     {
      19.         this._eventHandlerMethods[i] = (MethodInfo) list[i];
      20.     }
      21. }
      22.
    23.
    
    可以看出theApplicationType中的函数信息是被保存到ArrayList类型中,并最终this._eventHandlerMethods[i] = (MethodInfo) list[i];存入_eventHandlerMethods成员变量中(MethodInfo[]类型 )
    接下来看一下ReflectOnMethodInfoIfItLooksLikeEventHandler(info)函数做的处理
    
       1. private bool ReflectOnMethodInfoIfItLooksLikeEventHandler(MethodInfo m)
       2. {
       3.     。。。。。。。
       4.     。。。。。。。
       5.     。。。。。。。
       6.     if (StringUtil.EqualsIgnoreCase(str, "Application_OnStart") || StringUtil.EqualsIgnoreCase(str, "Application_Start"))
       7.     {
       8.         this._onStartMethod = m;
       9.         this._onStartParamCount = parameters.Length;
      10.     }
      11.     else if (StringUtil.EqualsIgnoreCase(str, "Application_OnEnd") || StringUtil.EqualsIgnoreCase(str, "Application_End"))
      12.     {
      13.         this._onEndMethod = m;
      14.         this._onEndParamCount = parameters.Length;
      15.     }
      16.     else if (StringUtil.EqualsIgnoreCase(str, "Session_OnEnd") || StringUtil.EqualsIgnoreCase(str, "Session_End"))
      17.     {
      18.         this._sessionOnEndMethod = m;
      19.         this._sessionOnEndParamCount = parameters.Length;
      20.     }
      21.     return true;
      22. }
      23.
    24.
    
    省略的部分是对theApplicationType中函数的检验(返回值,参数)
    如之前所说Application_OnStart函数(或Application_Start),Application_OnEnd函数(或Application_End),Session_OnEnd函数(或Session_End),若theApplicationType中存在这三个函数信息会被存贮在HttpApplicationFactory,并在适当的时机,通过invoke来调用,所以在HttpApplication中事件并不包括此三类。
    
    这样整个HttpApplicationFactory的Init处理就完成了。
    
    回顾上述GetApplicationInstance(HttpContext context) 方法
    接下来要做的就是_theApplicationFactory.EnsureAppStartCalled(context); 创建特定的HttpApplication实例,触发ApplicationOnStart事件,执行ASP.global_asax中的 Application_Start(object sender, EventArgs e)方法。这里创建的HttpApplication实例在处理完事件后,就被回收。
    这里不详细分析了,有兴趣可以去找一下:)形如以下操作
    _onStartMethod.Invoke(this, new object[] { eventSource, eventArgs })
    
    最后总算可以取HttpApplication实例了,在这之中,我们看一下HttpApplication初始化的实现
    
       1. private HttpApplication GetNormalApplicationInstance(HttpContext context)
       2. {
       3.     HttpApplication application = null;
       4.     lock (this._freeList)
       5.     {
       6.         if (this._numFreeAppInstances > 0)
       7.         {
       8.             application = (HttpApplication) this._freeList.Pop();
       9.             。。。。。。。
      10.         }
      11.     }
      12.     if (application == null)
      13.     {
      14.         application = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);
      15.         using (new ApplicationImpersonationContext())
      16.         {
      17.             application.InitInternal(context, this._state, this._eventHandlerMethods);
      18.         }
      19.     }
      20.     return application;
      21. }
      22.
    23.
    
    04到10的操作是在ApplicationFactory池中取空闲的HttpApplication(当客户端程序结束后HttpApplication不会被释放,而是被存在ApplicationFactory池中供其它用户复用,这样显然更有效),如果不存在则进行初始化创建
    接下来我们看一下HttpApplication级的初始化操作
    
       1. internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)
       2. {
       3.     。。。。。。。
       4.     try
       5.     {
       6.         try
       7.         {
       8.             。。。。。。。。。。。。
       9.             using (new HttpContextWrapper(context))
      10.             {
      11.                 。。。。。。。。
      12.                 this.InitModules();
      13.             Label_006B:
      14.                 if (handlers != null)
      15.                 {
      16.                     this.HookupEventHandlersForApplicationAndModules(handlers);
      17.                 }
      18.                 。。。。。。
      19.                 。。。。。。。
      20.                 try
      21.                 {
      22.                     this.Init();
      23.                 }
      24.                 catch (Exception exception)
      25.                 {
      26.                     。。。。。。。。。。。
      27.                 }
      28.             }
      29.             。。。。。。。。。。。
      30.             if (HttpRuntime.UseIntegratedPipeline)
      31.             {
      32.                 this._stepManager = new PipelineStepManager(this);
      33.             }
      34.             else
      35.             {
      36.                 this._stepManager = new ApplicationStepManager(this);
      37.             }
      38.             this._stepManager.BuildSteps(this._resumeStepsWaitCallback);
      39.         }
      40.         finally
      41.         {
      42.             。。。。。。。。
      43.         }
      44.     }
      45.     catch
      46.     {
      47.         throw;
      48.     }
      49. }
      50.
    
    在这个方法中,首先this.InitModules();这里做的是1.从配置文件中读取节点内容(machine.config web.config) 2.创建HttpModules模块并逐一调用HttpModule的Init初始化方法(HttpModules相关内容这里不作介绍)
    
    this.HookupEventHandlersForApplicationAndModules(handlers);参数handlers其实就是保存在ApplicationFactory中ApplicationType中的函数信息(以上提到过)。根据HttpApplication的事件信息,进行动态的创建委托,并且进行方法的绑定(指针挂钩),但是对函数名有要求
    例如:事件BeginRequest 能自动绑定的函数名为 Application_OnBeginRequest 或者 Application_BeginRequest
    若函数名不为上述名称,想绑定事件BeginRequest的话,可在this.Init()中通过委托绑定(+=),这是个虚拟函数(多态)
    
    this._stepManager.BuildSteps(this._resumeStepsWaitCallback);
    
       1. internal override void BuildSteps(WaitCallback stepCallback)
       2. {
       3.     ArrayList steps = new ArrayList();
       4.     。。。。。。。。。。。
       5.     app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);
       6.     app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);
       7.     app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);
       8.     app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);
       9.     app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);
      10.     app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);
      11.     app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);
      12.     app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);
      13.     steps.Add(new HttpApplication.MapHandlerExecutionStep(app));
      14.     app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);
      15.     app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);
      16.     app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);
      17.     app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);
      18.     steps.Add(new HttpApplication.CallHandlerExecutionStep(app));
      19.     app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);
      20.     app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);
      21.     app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);
      22.     steps.Add(new HttpApplication.CallFilterExecutionStep(app));
      23.     app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);
      24.     app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);
      25.     this._endRequestStepIndex = steps.Count;
      26.     app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps);
      27.     steps.Add(new HttpApplication.NoopExecutionStep());
      28.     this._execSteps = new HttpApplication.IExecutionStep[steps.Count];
      29.     steps.CopyTo(this._execSteps);
      30.     this._resumeStepsWaitCallback = stepCallback;
      31. }
      32.
    
    可以看到这个方法创建了事件函数执行顺序,通过不同的类将事件函数封装后,并最终存入_execSteps。
    值得注意的是steps.Add(new HttpApplication.MapHandlerExecutionStep(app));和steps.Add(new HttpApplication.CallHandlerExecutionStep(app));
    前者读取HttpHandle节点配置,后者则是调用HttpHandle节点中类,进行处理。留意一下它们所处的事件流程的位置
    
    以上的阶段,是HttpApplication的初始化阶段。
    取得HttpApplication实例后就是按照上述取得_execSteps来依次执行事件函数的调用了
    回顾HttpRuntime类中的ProcessRequestInternal(HttpWorkerRequest wr) 函数,有这么一段
    #         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);
    #         }
    对于取得HttpApplication实例的类型判断,如果实现的是异步接口调用BeginProcessRequest,非异步接口调用ProcessRequest
    但实际上HttpApplication的非异步接口会抛出异常,.Net只支持异步的调用
    
    void IHttpHandler.ProcessRequest(HttpContext context)
    {
        throw new HttpException(SR.GetString("Sync_not_supported"));
    }
    
    handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context)实现中
    通过调用this.ResumeSteps(null) 并最终调用到HttpApplication的内部类
    ApplicationStepManager的 ResumeSteps函数。
    
       1. [DebuggerStepperBoundary]
       2. internal override void ResumeSteps(Exception error)
       3. {
       4.     。。。。。。
       5.     lock (base._application)
       6.     {
       7.         。。。。。。
       8.         try
       9.         {
      10.             try
      11.             {
      12.             Label_0040:
      13.                 if (syncContext.Error != null)
      14.                 {
      15.                     。。。。。
      16.                 }
      17.                 if (error != null)
      18.                 {
      19.                     。。。。。。
      20.                 }
      21.                 if (syncContext.PendingOperationsCount > 0)
      22.                 {
      23.                     。。。。。。。
      24.                 }
      25.                 else
      26.                 {
      27.                     if ((this._currentStepIndex < this._endRequestStepIndex) && ((context.Error != null) || base._requestCompleted))
      28.                     {
      29.                         context.Response.FilterOutput();
      30.                         this._currentStepIndex = this._endRequestStepIndex;
      31.                     }
      32.                     else
      33.                     {
      34.                         this._currentStepIndex++;
      35.                     }
      36.                     if (this._currentStepIndex >= this._execSteps.Length)
      37.                     {
      38.                         flag = true;
      39.                     }
      40.                     else
      41.                     {
      42.                         this._numStepCalls++;
      43.                         context.SyncContext.Enable();
      44.                         error = application.ExecuteStep(this._execSteps[this._currentStepIndex], ref completedSynchronously);
      45.                         if (completedSynchronously)
      46.                         {
      47.                             this._numSyncStepCalls++;
      48.                             goto Label_0040;
      49.                         }
      50.                     }
      51.                 }
      52.             }
      53.             finally
      54.             {
      55.                 。。。。。。
      56.             }
      57.         }
      58.         catch
      59.         {
      60.             throw;
      61.         }
      62.     }
      63.     if (flag)
      64.     {
      65.         。。。。。。
      66. }
    67.
    
    其中error = application.ExecuteStep(this._execSteps[this._currentStepIndex], ref completedSynchronously);
    便是通过_execSteps来依次执行事件函数的调用了,并最终通过step.Execute()调用
    
    以下只对执行HttpHandle的过程做一个了解
    
    之前知道steps.Add(new HttpApplication.CallHandlerExecutionStep(app));已经创建了事件顺序
    接下来就是看一下CallHandlerExecutionStep中Execute的实现了
    
       1. void HttpApplication.IExecutionStep.Execute()
       2. {
       3.     HttpContext context = this._application.Context;
       4.     IHttpHandler handler = context.Handler;
       5.     。。。。。。
       6.     。。。。。。
       7.     if (handler is IHttpAsyncHandler)
       8.     {
       9.         。。。。。。
      10.         IAsyncResult result = handler2.BeginProcessRequest(context, this._completionCallback, null);
      11.         if (result.CompletedSynchronously)
      12.         {
      13.             。。。。。。。
      14.         }
      15.     }
      16.     else
      17.     {
      18.         。。。。。。。。
      19.         try
      20.         {
      21.             handler.ProcessRequest(context);
      22.         }
      23.         finally
      24.         {
      25.             。。。。。。
      26.         }
      27.     }
      28. }
      29.
    
    以上程序可以看出根据HttpHandle所继承的接口,分别调用BeginProcessRequest或者ProcessRequest
    另外HttpHandle实例的创建正是之前steps.Add(new HttpApplication.MapHandlerExecutionStep(app))的Execute完成的
    Execute中
    context.Handler = this._application.MapHttpHandler(。。。。。);取得
    值得注意的是MapHttpHandler中通过读取配置文件,首先判断HttpHandle节点是否有自定义IHttpHandlerFactory处理,有的话生成该类实例,如果没有,则生成默认类HandlerFactoryCache
    最后通过IHttpHandlerFactory的接口函数GetHandler取得处理句柄(默认句柄情况下就是配置文件HttpHandle节点的处理类,若不存在会报错)
    经过几个事件函数的调用后,
    在CallHandlerExecutionStep的Execute中被处理(如上)
    
    在所有事件函数被调用完成之后,HttpApplication实例会被回收,ISAPIRuntime.ProcessRequest处理完毕,结果返回给COM,并通过COM的再一次处理,返回给客户端。这样一次请求就至此结束了。
    这个文章主要针对的是HttpApplication层面的,下次如果有时间再对aspx文件的HttpHandle层面的重要类Page也做一个分析
  • 相关阅读:
    数据仓库建设随笔(2)
    实战剖析三层架构2:实例代码
    数据仓库建设随笔(1)
    如何正确地死磕一个问题
    finally块中的代码一定会执行吗
    eclipse中任务进度的使用
    如何在单元测试编码实现类的访问器?这里给出一个答案
    SplitContainer.SplitterDistance属性值设置应注意的与FixedPanel有关
    再谈ReportingService报表中数据源类型为存储过程的数据集如何使用多值参数
    工作流加载及本地通信服务常见的异常
  • 原文地址:https://www.cnblogs.com/pipizhu/p/2583551.html
Copyright © 2011-2022 走看看