主要類
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 運行時而寫的歡迎你對文章內容提出批評與建議
From:http://tw.wingwit.com/Article/program/net/201311/14192.html