在我的上一篇文章中说到了HttpModuleHttpHandle的简单使用我们可以利用它们在页面请求的过程中加入自己的事件处理程序那么在一个aspx页面请求时后台到底做了什么?当然做了很多事情过程也比较复杂本文主要分析一下大体的流程总体流程如下
请求一个页面时首先被WWW服务截获(inetinfoexe进程)这个进程首先判断页面的后缀然后根据IIS中的配置来决定调用哪个扩展程序比如aspx的页面就会调用c:\windows\\framework\v\aspnet_isapidllaspnet_isapidll将请求发送给wwpexe进程(我们在调试IIS中网站时就是把VS附加到这个进程上的)
接下来wwpexe进程就会调类库进行具体处理
ISAPIRuntime>HttpRuntime>HttpApplicationFactory>HttpApplication>HttpModuleHttpHandlerFactory>HttpHandler 这也是本文主要分析的地方
下面只是列出主要流程如果喜欢钻研的同学可以用Reflector去查看
一ISAPIRuntime
bool useOOP = iWRType == ;
wr = ISAPIWorkerRequestCreateWorkerRequest(ecb useOOP);
wrInitialize();
string appPathTranslated = wrGetAppPathTranslated();
string appDomainAppPathInternal = HttpRuntimeAppDomainAppPathInternal;
if ((appDomainAppPathInternal == null) || StringUtilEqualsIgnoreCase(appPathTranslated appDomainAppPathInternal))
{
HttpRuntimeProcessRequestNoDemand(wr);
return ;
}
HttpRuntimeShutdownAppDomain(ApplicationShutdownReasonPhysicalApplicationPathChanged SRGetString(Hosting_Phys_Path_Changed new object[] { appDomainAppPathInternal appPathTranslated }));
return ;
它的主要作用是调用一些非托管代码生成HttpWorkerRequest对象该对象包含当前请求的所有信息然后传递给HttpRuntime这里生成的HttpWorkerRequest对象可以直接在我们的页面中调用的通过它取得原始的请求信息
IServiceProvider provider = (IServiceProvider)HttpContextCurrent;
HttpWorkerRequest wr = (HttpWorkerRequest)providerGetService(typeof(HttpWorkerRequest));
二HttpRuntime
最主要的就是private void ProcessRequestInternal(HttpWorkerRequest wr)方法 context = new HttpContext(wr false);
IHttpHandler applicationInstance = HttpApplicationFactoryGetApplicationInstance(context);
IHttpAsyncHandler handler = (IHttpAsyncHandler) applicationInstance;
contextAsyncAppHandler = handler;
handlerBeginProcessRequest(context this_handlerCompletionCallback context);
根据HttpWorkerRequest对象生成HttpContextHttpContext应该大家都很熟悉的它包含requestresponse等属性在页面中经常会用到的
调用HttpApplicationFactory来生成IHttpHandler(这里生成的是一个默认的HttpApplication对象HttpApplication也是IHttpHandler接口的一个实现)
调用HttpApplication对象执行请求
三HttpApplicationFactory
正如中所提到的这里主要是生成一个HttpApplication对象
internal static string GetApplicationFile()
{
return PathCombine(HttpRuntimeAppDomainAppPathInternal globalasax);
}
首先会查看是否存在globalasax文件如果有的话就用它来生成HttpApplication对象从这里我们可以看到globalasax的文件名是在的框架中写死的不能修改的如果这个文件不存在就使用默认的对象
创建好HttpApplication之后对它进行初始化
application = (HttpApplication) HttpRuntimeCreateNonPublicInstance(this_theApplicationType);
using (ApplicationImpersonationContext context = new ApplicationImpersonationContext())
{
applicationInitInternal(context this_state this_eventHandlerMethods);
}
四HttpApplication
这个是比较复杂也比较重要的一个对象
首先是执行初始化操作比较重要的一步就是进行HttpModule的初始化 private void InitModules()
{
this_moduleCollection = RuntimeConfigGetAppConfig()HttpModulesCreateModules();
thisInitModulesCommon();
}它会读取nfig中所有HttpModule的配置
在HookupEventHandlersForApplicationAndModules方法中绑定Module的事件处理程序接着进行事件实际绑定
if (HttpRuntimeUseIntegratedPipeline)
{
this_stepManager = new PipelineStepManager(this);
}
else
{
this_stepManager = new ApplicationStepManager(this);
}
this_stepManagerBuildSteps(this_resumeStepsWaitCallback);
在ApplicationStepManager的BuildSteps方法中可以看到事件的绑定执行顺序
appCreateEventExecutionSteps(HttpApplicationEventBeginRequest steps);
appCreateEventExecutionSteps(HttpApplicationEventAuthenticateRequest steps);
appCreateEventExecutionSteps(HttpApplicationEventDefaultAuthentication steps);
appCreateEventExecutionSteps(HttpApplicationEventPostAuthenticateRequest steps);
appCreateEventExecutionSteps(HttpApplicationEventAuthorizeRequest steps);
appCreateEventExecutionSteps(HttpApplicationEventPostAuthorizeRequest steps);
appCreateEventExecutionSteps(HttpApplicationEventResolveRequestCache steps);
appCreateEventExecutionSteps(HttpApplicationEventPostResolveRequestCache steps);
stepsAdd(new HttpApplicationMapHandlerExecutionStep(app));
appCreateEventExecutionSteps(HttpApplicationEventPostMapRequestHandler steps);
appCreateEventExecutionSteps(HttpApplicationEventAcquireRequestState steps);
appCreateEventExecutionSteps(HttpApplicationEventPostAcquireRequestState steps);
appCreateEventExecutionSteps(HttpApplicationEventPreRequestHandlerExecute steps);
stepsAdd(new HttpApplicationCallHandlerExecutionStep(app));
appCreateEventExecutionSteps(HttpApplicationEventPostRequestHandlerExecute steps);
appCreateEventExecutionSteps(HttpApplicationEventReleaseRequestState steps);
appCreateEventExecutionSteps(HttpApplicationEventPostReleaseRequestState steps);
stepsAdd(new HttpApplicationCallFilterExecutionStep(app));
appCreateEventExecutionSteps(HttpApplicationEventUpdateRequestCache steps);
appCreateEventExecutionSteps(HttpApplicationEventPostUpdateRequestCache steps);
this_endRequestStepIndex = stepsCount;
appCreateEventExecutionSteps(HttpApplicationEventEndRequest steps);
stepsAdd(new HttpApplicationNoopExecutionStep());
注意上面红色标注的MapHandlerExecutionStep(读取所有的HttpHandler配置)CallHandlerExecutionStep就是对Handle程序进行处理的也就是说在nfig中配置的HttpHandler都是在这里进行处理的执行顺序如上所示
然后就是调用中的方法执行请求
Code
IAsyncResult IHttpAsyncHandlerBeginProcessRequest(HttpContext context AsyncCallback cb object extraData)
{
this_context = context;
this_contextApplicationInstance = this;
this_stepManagerInitRequest();
this_contextRoot();
HttpAsyncResult result = new HttpAsyncResult(cb extraData);
thisAsyncResult = result;
if (this_contextTraceIsEnabled)
{
HttpRuntimeProfileStartRequest(this_context);
}
thisResumeSteps(null);
return result;
}
在ResumeSteps中就是执行事件处理程序
五HttpModule
在系统nfig中默认的配置有
Code
<httpModules>
<add name=OutputCache type=SystemWebCachingOutputCacheModule/>
<add name=Session type=SystemWebSessionStateSessionStateModule/>
<add name=WindowsAuthentication type=SystemWebSecurityWindowsAuthenticationModule/>
<add name=FormsAuthentication type=SystemWebSecurityFormsAuthenticationModule/>
<add name=PassportAuthentication type=SystemWebSecurityPassportAuthenticationModule/>
<add name=RoleManager type=SystemWebSecurityRoleManagerModule/>
<add name=UrlAuthorization type=SystemWebSecurityUrlAuthorizationModule/>
<add name=FileAuthorization type=SystemWebSecurityFileAuthorizationModule/>
<add name=AnonymousIdentification type=SystemWebSecurityAnonymousIdentificationModule/>
<add name=Profile type=SystemWebProfileProfileModule/>
<add name=ErrorHandlerModule type=SystemWebMobileErrorHandlerModule SystemWebMobile Version= Culture=neutral PublicKeyToken=bfffdaa/>
<add name=ServiceModel type=SystemServiceModelActivationHttpModule SystemServiceModel Version= Culture=neutral PublicKeyToken=bace/>
</httpModules>
基本使用方法可以参见我的上一篇文章
六HttpHandlerFactoryHttpHandler
这两个对象在nfig中的配置方法是相同的默认配置有
Code
<add path=*rules verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*xoml verb=* type=SystemServiceModelActivationHttpHandler SystemServiceModel Version= Culture=neutral PublicKeyToken=bace validate=false/>
<add path=traceaxd verb=* type=SystemWebHandlersTraceHandler validate=true/>
<add path=WebResourceaxd verb=GET type=SystemWebHandlersAssemblyResourceLoader validate=true/>
<add path=*axd verb=* type=SystemWebHttpNotFoundHandler validate=true/>
<add path=*aspx verb=* type=SystemWebUIPageHandlerFactory validate=true/>
<add path=*ashx verb=* type=SystemWebUISimpleHandlerFactory validate=true/>
<add path=*asmx verb=* type=SystemWebServicesProtocolsWebServiceHandlerFactory SystemWebServices Version= Culture=neutral PublicKeyToken=bfffdaa validate=false/>
<add path=*rem verb=* type=SystemRuntimeRemotingChannelsHttpHttpRemotingHandlerFactory SystemRuntimeRemoting Version= Culture=neutral PublicKeyToken=bace validate=false/>
<add path=*soap verb=* type=SystemRuntimeRemotingChannelsHttpHttpRemotingHandlerFactory SystemRuntimeRemoting Version= Culture=neutral PublicKeyToken=bace validate=false/>
<add path=*asax verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*ascx verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*master verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*skin verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*browser verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*sitemap verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*nfig verb=GETHEAD type=SystemWebStaticFileHandler validate=true/>
<add path=*nfig verb=GETHEAD type=SystemWebStaticFileHandler validate=true/>
<add path=nfig verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*cs verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*csproj verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*vb verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*vbproj verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*webinfo verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*licx verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*resx verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*resources verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*mdb verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*vjsproj verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*java verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*jsl verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*ldb verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*ad verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*dd verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*ldd verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*sd verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*cd verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*adprototype verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*lddprototype verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*sdm verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*sdmDocument verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*mdf verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*ldf verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*exclude verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*refresh verb=* type=SystemWebHttpForbiddenHandler validate=true/>
<add path=*svc verb=* type=SystemServiceModelActivationHttpHandler SystemServiceModel Version= Culture=neutral PublicKeyToken=bace validate=false/>
<add path=* verb=GETHEADPOST type=SystemWebDefaultHttpHandler validate=true/>
<add path=* verb=* type=SystemWebHttpMethodNotAllowedHandler validate=true/>
</httpHandlers>
要注意的是相同的后缀名配置多次的话后面的配置会把前面的覆盖
这里我们重点看一下aspx的配置SystemWebUIPageHandlerFactory
这是一个HttpHandlerFactory对象根据不同的Page生成不同的HttpHandler对象(我们自己的Page页面都是一个IHttpHandler)
Page page = BuildManagerCreateInstanceFromVirtualPath(virtualPath typeof(Page) context true true) as Page;
if (page == null)
{
return null;
}
pageTemplateControlVirtualPath = virtualPath;
return page;
这里会调用nfig中的buildProviders配置编译页面
Code
<buildProviders>
<add extension=aspx type=SystemWebCompilationPageBuildProvider/>
<add extension=ascx type=SystemWebCompilationUserControlBuildProvider/>
<add extension=master type=SystemWebCompilationMasterPageBuildProvider/>
<add extension=asmx type=SystemWebCompilationWebServiceBuildProvider/>
<add extension=ashx type=SystemWebCompilationWebHandlerBuildProvider/>
<add extension=soap type=SystemWebCompilationWebServiceBuildProvider/>
<add extension=resx type=SystemWebCompilationResXBuildProvider/>
<add extension=resources type=SystemWebCompilationResourcesBuildProvider/>
<add extension=wsdl type=SystemWebCompilationWsdlBuildProvider/>
<add extension=xsd type=SystemWebCompilationXsdBuildProvider/>
<add extension=js type=SystemWebCompilationForceCopyBuildProvider/>
<add extension=lic type=SystemWebCompilationIgnoreFileBuildProvider/>
<add extension=licx type=SystemWebCompilationIgnoreFileBuildProvider/>
<add extension=exclude type=SystemWebCompilationIgnoreFileBuildProvider/>
<add extension=refresh type=SystemWebCompilationIgnoreFileBuildProvider/>
<add extension=xoml type=SystemServiceModelActivationWorkflowServiceBuildProvider SystemWorkflowServices Version= Culture=neutral PublicKeyToken=bfade/>
<add extension=svc type=SystemServiceModelActivationServiceBuildProvider SystemServiceModel Version= Culture=neutral PublicKeyToken=bace/>
</buildProviders>
这样就可以进入我们的Page执行了大的执行顺序可以参见第四部分的描述它也就是一个HttpHandler