Asp.Net页面执行流程分析

在我的上一篇文章中说到了HttpModule、HttpHandle的简单使用,我们可以利用它们在页面请求的过程中加入自己的事件处理程序。那么在一个aspx页面请求时后台到底做了什么?当然asp.net做了很多事情,过程也比较复杂,本文主要分析一下大体的流程。 总体流程如下:
请求一个页面时首先被WWW服务截获(inetinfo.exe进程),这个进程首先判断页面的后缀,然后根据IIS中的配置来决定调用哪个扩展程序,比如aspx的页面就会调用c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll,aspnet_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);
return0;
}

HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged,SR.GetString(
" Hosting_Phys_Path_Changed " , new object [] {appDomainAppPathInternal,appPathTranslated} ));
return 1 ;
它的主要作用是调用一些非托管代码生成HttpWorkerRequest对象,该对象包含当前请求的所有信息,然后传递给HttpRuntime,这里生成的HttpWorkerRequest对象可以直接在我们的页面中调用的,通过它取得原始的请求信息:
IServiceProviderprovider=(IServiceProvider)HttpContext.Current;
HttpWorkerRequestwr
=(HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));

二:HttpRuntime

最主要的就是private void ProcessRequestInternal(HttpWorkerRequest wr)方法:
context = new HttpContext(wr, false );

IHttpHandlerapplicationInstance
= HttpApplicationFactory.GetApplicationInstance(context);

IHttpAsyncHandlerhandler2
= (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()
{
returnPath.Combine(HttpRuntime.AppDomainAppPathInternal,"global.asax");
}

首先会查看是否存在global.asax文件,如果有的话就用它来生成HttpApplication对象,从这里我们可以看到global.asax的文件名是在asp.net的框架中写死的,不能修改的。如果这个文件不存在就使用默认的对象。
创建好HttpApplication之后对它进行初始化:
application = (HttpApplication)HttpRuntime.CreateNonPublicInstance( this ._theApplicationType);
using (ApplicationImpersonationContextcontext2 = 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=newPipelineStepManager(this);
}

else
{
this._stepManager=newApplicationStepManager(this);
}

this ._stepManager.BuildSteps( this ._resumeStepsWaitCallback);

在ApplicationStepManager的BuildSteps方法中可以看到事件的绑定执行顺序:

app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest,steps);
app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest,steps);
app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication,steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest,steps);
app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest,steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest,steps);
app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache,steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache,steps);
steps.Add(newHttpApplication.MapHandlerExecutionStep(app));
app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler,steps);
app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState,steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState,steps);
app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute,steps);
steps.Add(newHttpApplication.CallHandlerExecutionStep(app));

app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute,steps);
app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState,steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState,steps);
steps.Add(
new HttpApplication.CallFilterExecutionStep(app));
app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache,steps);
app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache,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
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->IAsyncResultIHttpAsyncHandler.BeginProcessRequest(HttpContextcontext,AsyncCallbackcb,objectextraData)
{
this._context=context;
this._context.ApplicationInstance=this;
this._stepManager.InitRequest();
this._context.Root();
HttpAsyncResultresult
=newHttpAsyncResult(cb,extraData);
this.AsyncResult=result;
if(this._context.TraceIsEnabled)
{
HttpRuntime.Profile.StartRequest(
this._context);
}

this.ResumeSteps(null);
returnresult;
}

在ResumeSteps中就是执行事件处理程序。

五、HttpModule

在系统web.config中默认的配置有:
Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><httpModules>
<addname="OutputCache"type="System.Web.Caching.OutputCacheModule"/>
<addname="Session"type="System.Web.SessionState.SessionStateModule"/>
<addname="WindowsAuthentication"type="System.Web.Security.WindowsAuthenticationModule"/>
<addname="FormsAuthentication"type="System.Web.Security.FormsAuthenticationModule"/>
<addname="PassportAuthentication"type="System.Web.Security.PassportAuthenticationModule"/>
<addname="RoleManager"type="System.Web.Security.RoleManagerModule"/>
<addname="UrlAuthorization"type="System.Web.Security.UrlAuthorizationModule"/>
<addname="FileAuthorization"type="System.Web.Security.FileAuthorizationModule"/>
<addname="AnonymousIdentification"type="System.Web.Security.AnonymousIdentificationModule"/>
<addname="Profile"type="System.Web.Profile.ProfileModule"/>
<addname="ErrorHandlerModule"type="System.Web.Mobile.ErrorHandlerModule,System.Web.Mobile,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"/>
<addname="ServiceModel"type="System.ServiceModel.Activation.HttpModule,System.ServiceModel,Version=3.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"/>
</httpModules>
基本使用方法可以参见我的上一篇文章

六、HttpHandlerFactory、HttpHandler

这两个对象在web.config中的配置方法是相同的,默认配置有:
Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><addpath="*.rules"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.xoml"verb="*"type="System.ServiceModel.Activation.HttpHandler,System.ServiceModel,Version=3.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"validate="false"/>
<addpath="trace.axd"verb="*"type="System.Web.Handlers.TraceHandler"validate="true"/>
<addpath="WebResource.axd"verb="GET"type="System.Web.Handlers.AssemblyResourceLoader"validate="true"/>
<addpath="*.axd"verb="*"type="System.Web.HttpNotFoundHandler"validate="true"/>
<addpath="*.aspx"verb="*"type="System.Web.UI.PageHandlerFactory"validate="true"/>
<addpath="*.ashx"verb="*"type="System.Web.UI.SimpleHandlerFactory"validate="true"/>
<addpath="*.asmx"verb="*"type="System.Web.Services.Protocols.WebServiceHandlerFactory,System.Web.Services,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"validate="false"/>
<addpath="*.rem"verb="*"type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,System.Runtime.Remoting,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"validate="false"/>
<addpath="*.soap"verb="*"type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,System.Runtime.Remoting,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"validate="false"/>
<addpath="*.asax"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.ascx"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.master"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.skin"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.browser"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.sitemap"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.dll.config"verb="GET,HEAD"type="System.Web.StaticFileHandler"validate="true"/>
<addpath="*.exe.config"verb="GET,HEAD"type="System.Web.StaticFileHandler"validate="true"/>
<addpath="*.config"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.cs"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.csproj"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.vb"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.vbproj"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.webinfo"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.licx"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.resx"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.resources"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.mdb"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.vjsproj"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.java"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.jsl"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.ldb"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.ad"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.dd"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.ldd"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.sd"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.cd"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.adprototype"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<addpath="*.lddprototype"verb="*"type="System.Web.HttpForbiddenHandler"validate="true"/>
<add
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值