代码改变世界

【转】ASP.NET页面请求管道流程

2012-07-09 19:04  cnb_mtime  阅读(461)  评论(0编辑  收藏  举报

[转]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也做一个分析