回到之前,當服務器在處理如aspx.ashx,等等動態文件的時候,IIS服務器將Request請求,交
給aspnet_isapi.dll文件來處理。
ISAPI是第一個也是性能最高Request請求報文最原始的Web請求切入點
aspnet_isapi.dll是一個非常底層,并且是非托管的win32API,這個dll非常簡單,非常高效,并且還被微軟優化過性能。它用來處理最底層的 指令以及函數回調,并為高層程序提供了應用程序級別服務的功能和接口。
當aspnet_isapi.dll接收到Request請求的時候,aspnet_isapi.dll就會去調動Web服務器中的.Net Framework,最終加載CLR運行環境,并創建一個ISAPIRuntime對象,然后調用ISAPIRuntime對象的
PRocessRequest()方法。
ISAPIRuntme.ProcessRequest()方法是進入ASP.Net的第一個入口
ISAPIRuntime.ProcessRequest()方法調用之后主要做了一件事情,就是將Request的原始請求信息封裝成HttpWorkRequest類,由于HttpWorkRequest類封裝的請求報文很原始,很復雜,所以微軟沒有將其公開出來。接著執行StartProcessing()方法,來創建HttpRuntime對象并調用其靜態方法ProcessRequest()。

圖三 : 如何開始ASP.Net
在HttpRuntime對象調用其靜態方法ProcessRequest()之后,我們的Web請求開始慢慢進入應用層級別,why?
ProcessRequest()這個方法做了很多事情,具體可以通過Reflector工具查看,但是大致分為四個部分:
1.為請求創建了一個新的HttpContext實例(這個對象就是我們常用的HttpContext上下文對象),并將HttpWorkRequest中最原始的請求
報文封裝到HttpContext對象的HttpRequest對象中。
2.通過HttpApplicationFactory(應用程序工廠)得到一個具體的HttpApplication 實例。
3.調用HttpApplication.Init()方法來建立事件請求管道。
4.Init()方法觸發了HttpApplication.ResumeProcessing()方法來開始執行Asp.Net事件請求管道。

圖四 : HttpRuntime,HttpApplication和HttpContext的關系
Asp.Net事件請求管道詳解
前面說Asp.Net是一個Aop框架,而Asp.Net事件請求管道就是一點。
Asp.Net事件請求管道,是微軟幫程序員提供來處理Web請求的一些列事件,這些事件是依次執行,我們可以通過在這些事件上注冊或移除我們自己寫的方法,來修改Web請求執行的邏輯。

圖五 : ASP.Net事件請求管道
在第八個事件的時候,會創建請求的頁面對象,并轉換為IHttpHandler接口。
在第九個事件到第十一個事件之間,會接收到瀏覽器發過來的
sessionId。并先會將IHttpHandler接口嘗試轉換為IRequiresSessionState接口,如果轉換成功,Asp.Net會根據這個SessionId到服務器的Session池中去查找所對應的Session對象,并將這個Session對象賦值到HttpContext對象的Session屬性。如果嘗試轉換為IRequiresSessionState接口不成功,則不加載Session。
在第十一個事件到第十二個事件之間,會調用在第八個事件創建的頁面對象的ProcessRequest方法。
當我們直接使用*.ashx頁面的時候,就直接調用了一個FrameworkInitialize(),并最終生成響應報文,發送回客戶端。
當我們在使用*.aspx頁面的時候,它繼承自Page類,而Page類實現了IHttpHandler接口。

由于Page類實現了IHttpHandler接口,在ProcessRequest方法中,調用了FrameworkInitialize()方法。

在FrameworkInitialize()這個方法內部就開始打造Asp.Net的頁面控件樹(打造html樹),在其中就調用了ProcessRequestMain方法,在這個方法里面就執行了整個Asp.Net頁面生命周期。
IHttpModules
請求通過事件管道,一些列的事件被觸發了,我們可以通過在Global.asax全局配置文件中看到這些事件。
但是由于這是由程序分配的事件,可能就不是我們想要的。如果我們想要創建一個能夠復用的HttpApplication事件管道來處理Web請求,
我們又想將這些代碼復用,或者開發成插件的形式。那么我們就可以使用IHttpModules。
IHttpModules配置很簡單,我們只需要在Web.config里面配置一下就可以了。而具體的HttpModules只需要實現IHttpModules接口,并注冊自己的方法就行了。
<?xml version="1.0"?>
<system.web>
<httpModules>
<add name="VEVbHttpModules" type="VEVb.VEVbHttpModules"/>
</httpModules>
</system.web>
</configuration>
Web.config文件的配置
publicclass VEVbHttpModules : IHttpModule
{
public void MyBeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
application.Context.Response.Write("這個IHttpModule具體類的寫法喲!");
}
}
具體的HttpModules類寫法
Asp.Net頁面生命周期詳解
Asp.Net是一個Aop框架,而Asp.Net事件請求管道體現了Aop思想,而現在我們要說的Asp.Net頁面生命周期也體現Aop思想。
Asp.Net頁面生命周期的本質就是微軟提供給我們程序員修改頁面控件樹代碼的一些列事件,我們可以通過實現頁面生命周期的事件方法來修改控件樹代碼。
圖六 : ASP.Net頁面生命周期
當ASP.Net執行完我們注冊的生命周期事件方法的時候,最后會調用Render方法,Render方法要求傳入一個TextWriter文本寫出器對象,并遍歷所有控件樹,調用每個控件的Render方法。
所以每一個控件調用Render方法之后產生的Html字符串都依次寫入到TextWriter對象。最后ASP.Net將TextWriter中的Html字符串封裝成響應報文,然后發送回客戶端。
結束語
在這里,我介紹了一下ASP.Net的整個處理請求的過程。但有很多底層的信息,我還沒有仔細去觀察過,因此很多細節可能還是沒有注意到。這篇文章可能還是有很多錯誤的地方,希望博客園的兄弟姐妹們糾錯,謝謝。