在我的上一篇文章中说到了HttpModule、HttpHandle的简单使用,我们可以利用它们在页面请求的过程中加入自己的事件处理程序。那么在一个aspx页面请求时后台到底做了什么?当然asp.net做了很多事情,过程也比较复杂,本文主要分析一下大体的流程。总体流程如下:
请求一个页面时首先被WWW服务截获(inetinfo.exe进程),这个进程首先判断页面的后缀,然后根据IIS中的配置来决定调用哪个扩展程序,比如aspx的页面就会调用c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll,aspneface="Verdana">t_isapi.dll将请求发送给w3wp.exe进程(我们在调试IIS中网站时就是把VS2005附加到这个进程上的)。接下来w3wp.exe进程就会调用.net类库进行具体处理:ISAPIRuntime-->HttpRuntime-->HttpApplicationFactory-->HttpApplication-->HttpModule--HttpHandlerFactory-->HttpHandler 这也是本文主要分析的地方。 下面只是列出主要流程,如果喜欢钻研的同学可以用Reflector去查看一下:
以下为引用的内容: ISAPIRuntime bool useOOP = iWRType == 1; wr = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP); wr.Initialize(); string appPathTranslated = wr.GetAppPathTranslated(); string appDomainAppPathInternal =
HttpRuntime.AppDomainAppPathInternal; if ((appDomainAppPathInternal == null) ||
StringUtil.EqualsIgnoreCase(appPathTranslated,
appDomainAppPathInternal)) { HttpRuntime.ProcessRequestNoDemand(wr); return 0; }
HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplica
tionPathChanged, SR.GetString("Hosting_Phys_Path_Changed", new object[]
{ appDomainAppPathInternal, appPathTranslated })); return 1; |
它的主要作用是调用一些非托管代码生成HttpWorkerRequest对象,该对象包含当前请求的所有信息,然后传递给HttpRuntime,这里生成的HttpWorkerRequest对象可以直接在我们的页面中调用的,通过它取得原始的请求信息:
以下为引用的内容: IServiceProvider provider =
(IServiceProvider)HttpContext.Current; HttpWorkerRequest wr =
(HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest)); |
二:HttpRuntime
最主要的就是private void ProcessRequestInternal(HttpWorkerRequest wr)方法:
以下为引用的内容: context = new HttpContext(wr, false); IHttpHandler applicationInstance =
HttpApplicationFactory.GetApplicationInstance(context); IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance; context.AsyncAppHandler = handler2; handler2.BeginProcessRequest(context,
this._handlerCompletionCallback, context); |
1、根据HttpWorkerRequest对象生成HttpContext,HttpContext应该大家都很熟悉的,它包含request、response等属性,在页面中经常会用到的;
2、调用HttpApplicationFactory来生成IHttpHandler(这里生成的是一个默认的HttpApplication对象,HttpApplication也是IHttpHandler接口的一个实现)
3、调用HttpApplication对象执行请求
三:HttpApplicationFactory
正如2.2中所提到的,这里主要是生成一个HttpApplication对象:
以下为引用的内容: internal static string GetApplicationFile() { return Path.Combine(HttpRuntime.AppDomainAppPathInternal,
"global.asax"); } |
首先会查看是否存在global.asax文件,如果有的话就用它来生成HttpApplication对象,从这里我们可以看到global.asax的文件名是在asp.net的框架中写死的,不能修改的。如果这个文件不存在就使用默认的对象。
创建好HttpApplication之后对它进行初始化:
以下为引用的内容: application = (HttpApplication)
HttpRuntime.CreateNonPublicInstance(this._theApplicationType); using (ApplicationImpersonationContext context2 = new
ApplicationImpersonationContext()) { application.InitInternal(context, this._state,
this._eventHandlerMethods); } |
四、HttpApplication这个是比较复杂也比较重要的一个对象首先是执行初始化操作,比较重要的一步就是进行HttpModule的初始化:
以下为引用的内容: private void InitModules() { this._moduleCollection =
RuntimeConfig.GetAppConfig().HttpModules.CreateModules(); this.InitModulesCommon(); }它会读取web.config中所有HttpModule的配置 在HookupEventHandlersForApplicationAndModules方法中绑定Module的事件处理 |
程序接着进行事件实际绑定:
以下为引用的内容: if (HttpRuntime.UseIntegratedPipeline) { this._stepManager = new PipelineStepManager(this); } else { this._stepManager = new ApplicationStepManager(this); } this._stepManager.BuildSteps(this._resumeStepsWaitCallback); 在ApplicationStepManager的BuildSteps方法中可以看到事件的绑定执行顺序:
app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest,
steps); app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest,
steps);
app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthenticatio
n, steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequ
est, steps); app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest,
steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest
, steps);
app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache,
steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCa
che, steps); steps.Add(new HttpApplication.MapHandlerExecutionStep(app));
app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandle
r, steps);
app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState,
steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestSt
ate, steps);
app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExe
cute, steps); steps.Add(new HttpApplication.CallHandlerExecutionStep(app));
app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerEx
ecute, steps);
app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState,
steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestSt
ate, steps); steps.Add(new HttpApplication.CallFilterExecutionStep(app)); app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache,
steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCac
he, steps); this._endRequestStepIndex = steps.Count; app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps); steps.Add(new HttpApplication.NoopExecutionStep());
|
注意上面红色标注的MapHandlerExecutionStep(读取所有的HttpHandler配置)、CallHandlerExecutionStep就是对Handle程序进行处理的,也就是说在web.config中配置的HttpHandler都是在这里进行处理的,执行顺序如上所示然后就是调用2.3中的方法执行请求:
以下为引用的内容: Code 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; } |
在ResumeSteps中就是执行事件处理程序。