主要类
SystemWebHttpRuntime
SystemWebHttpApplicationFactory
SystemWebHttpApplication
SystemWebCompilationBuildManager
SystemWebCompilationApplicationBuildProvider
SystemWebCompilationBuildProvidersCompiler
SystemWebUIPageHandlerFactory
请求处理简要流程图:
阅读建议
用Reflector工具边查看ASPNET 的源代码边阅读
分析
当我们通过浏览器向ASPNET 网站的一个aspnet页面发起请求时在服务器端首先是IIS收到请求IIS一看是aspnet页面心里很开心因为这个请求不用它处理交给ASPNET ISAPI就行了ASPNET ISAPI的工作也比较轻松他的主要任务就是安排aspnet_wpexe处理请求并监视aspnet_wpexe进程的执行情况如果aspnet_wpexe进程太累了不能出色地完成任务ASPNET ISAPI就要让他下岗换一个新的aspnet_wpexe来处理工作
aspnet_wpexe的主要任务是将请求交给一系列称为的 HTTP 管道的托管对象如果把ASPNET ISAPI比做销售经理那aspnet_wpexe就是生产经理而HTTP 管道就是生产的流水线负责流水线的小组就是HttpRuntime生产经理aspnet_wpexe会将订单(HTTP请求)交给HttpRuntime小组的工作人员ProcessRequest(HttpWorkerRequest wr)HttpRuntime根据内部的分工最终由ProcessRequestInternal(HttpWorkerRequest wr)在流水线上进行生产所以ProcessRequestInternal(HttpWorkerRequest wr)是我们分析的重点
ProcessRequestInternal的主要工作是
创建HttpContext实例
对第一次请求进行初始化(EnsureFirstRequestInit)
a) 在EnsureFirstRequestInit中通过调用SystemWebHttpRuntimeFirstRequestInit进行一些初始化工作比如将WebConfig配置读到到RuntimeConfig中从bin目录中装载所有dll文件
创建HttpWriter实例
通过调用HttpApplicationFactoryGetApplicationInstance创建HttpApplication实例
在HttpApplicationFactoryGetApplicationInstance中有三个关键方法
HttpApplicationFactory_theApplicationFactoryEnsureInited();
HttpApplicationFactory_theApplicationFactoryEnsureAppStartCalled(context);
HttpApplicationFactory_theApplicationFactoryGetNormalApplicationInstance(context);
下面我们对这三个方法逐个进行分析
) HttpApplicationFactory_theApplicationFactoryEnsureInited();
该方法检查HttpApplicationFactory是否被初始化如果没有就通过HttpApplicationFactoryInit()进行初始化
在Init()中先获取globalasax文件的完整路径然后调用CompileApplication()对globalasax进行编译
那编译是如何进行的呢?
编译的工作由BuildManager完成的BuildManager先得到GlobalAsaxType(也就是HttpApplication)然后调用BuildManagerGetGlobalAsaxBuildResult()=》GetGlobalAsaxBuildResultInternal()=》EnsureTopLevelFilesCompiled()进行编译
在EnsureTopLevelFilesCompiled中先进行CompilationStageTopLevelFiles编译对下面三个目录中的文件进行编译
a CompileResourcesDirectory();
编译App_GlobalResources目录
b CompileWebRefDirectory();
编译App_WebReferences目录
c CompileCodeDirectories();
编译App_Code目录
接着进行CompilationStageGlobalAsax 编译对globalasax进行编译方法调用情况CompileGlobalAsax()=》ApplicationBuildProviderGetGlobalAsaxBuildResult(BuildManagerIsPrecompiledApp)
在GetGlobalAsaxBuildResult中具体的编译是由ApplicationBuildProvider与BuildProvidersCompiler共同完成的
BuildProvidersCompilerPerformBuild();进行编译工作
ApplicationBuildProviderGetBuildResult得到编译的结果
编译成功后会在C:WINDOWSMicrosoftNETFrameworkvTemporary ASPNET Files相应的目录中生成类似App_globalasaxmlgxnvdll的dll文件
编译生成的类名为ASPglobal_asax继承自HttpApplication
注如果Web目录中没有Globalasax文件就不会编译生成App_globalasaxmlgxnvdll这样的文件
) HttpApplicationFactory_theApplicationFactoryEnsureAppStartCalled(context);
创建特定的HttpApplication实例触发ApplicationOnStart事件执行ASPglobal_asax中的Application_Start(object sender EventArgs e)方法这里创建的HttpApplication实例在处理完事件后就被回收
) HttpApplicationFactory_theApplicationFactoryGetNormalApplicationInstance(context);
该方法创建HttpApplication实例并进行初始化(调用SystemWebHttpApplication InitInternal()方法)
创建HttpApplication实例是根据实际的_theApplicationType进行创建如果Web目录中没有globalasa文件也就是说没有动态编译生成ASPglobal_asax类型那就直接实例化HttpApplication如果创建了ASPglobal_asax类型那就对ASPglobal_asa进行实例化
创建HttpApplication实例之后就是调用实例的InitInternal方法
InitInternal方法也是我们重点分析的方法该方法的主要功能如下
InitModules()根据WebConfig的设置创建相应的HttpModules
HookupEventHandlersForAppplicationAndModules根据发生的事件调用HttpApplication实例中相应的事件处理函数
创建很多实现IExecutionStep接口的类的实例并添加到当前HttpApplication实例的_execSteps中等待回调时执行从这里我们可以看到HttpApplication是以异步的方式处理请求对请求的很多处理工作都放入了_execStep等待回调时执行
_execStep中主要的处理工作如下
) 对请求的路径进行安全检查禁止非法路径访问(ValidatePathExecutionStep)
) 如果设置了UrlMappings 进行RewritePath(UrlMappingsExecutionStep)
) 执行事件处理函数比如BeginRequestAuthenticateRequest等等
) 获取处理当前请求的HttpHandlerASPNET页面的运行时编译也是在这里进行的(MapHandlerExecutionStep)
该处理是通过调用SystemWebHttpApplication MapHttpHandler方法
在MapHttpHandler中首先根据访问的地址从webconfig获取相应的实现IHttpHandlerFactory的类型对于aspnet页面默认是PageHanlderFactory然后创建PageHanlderFactory实例调用GetHandlerHelper在GetHandlerHelper中调用BuildManagerCreateInstanceFromVirtualPath编译并创建当前请求的ASPNET页面的实例(如果已经编译过直接从缓存中加载)
CreateInstanceFromVirtualPath经过几次方法调用将编译任务给了BuildManager CompileWebFile()CompileWebFile从webconfig得到相应的BuildProvider对于aspx文件相应的BuildProvider是PageBuildProviderPageBuildProvider是如何进行页面编译的这里就不再就进一步分析了如果你感兴趣可以进一步研究ASPNET 的源代码
) 调用相应HttpHandler的ProcessRequest方法处理请求(如果是异步方式调用BeginProcessReques)(CallHandlerExecutionStep)
) 将响应内容写入Filter(CallFilterExecutionStep)
调用HttpApplication实例的BeginProcessRequest异步处理请求
上面所讲的_execSteps中所发生的许多事情都是在HttpRuntime调用HttpApplication BeginProcessRequest之后在BeginProcessRequest中调用ResumeSteps后执行的
ASPNET 运行时是ASPNET 中非常复杂难以理解也是很重要的部分对ASPNET 运行时源代码的研究有处于我们加深对ASPNET 原理的理解会给我们开发ASPNET 应用程序带来不少帮助这篇文章是我初次学习ASPNET 运行时为了帮助自己更好地理解ASPNET 运行时而写的欢迎你对文章内容提出批评与建议