在我的上一篇文章中說到了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
From:http://tw.wingwit.com/Article/program/net/201311/13812.html