1、引言
2、兩個處理步驟
2.1、建立ASP.NET環境
2.2、用觸發的MHPM事件處理請求
3、什麼事件中應該做什麼
4、示例代碼
5、深入ASP.NET頁面事件
這
篇文章我們将試圖了解,從使用者發送一個請求直到請求呈現到浏覽器發生的事件的差異。是以,我們首先将介紹解ASP.NET請求的兩個概括的步驟,接下來我
們将介紹‘HttpHandler’,‘HttpModule’和ASP.NET頁面對象發出的事件的差異。随着我們的事件旅程,我們将了解這些事件的邏
輯。
ASP.NET請求處理可以總結為如下所示的兩個處理步驟。使用者發送一個請求到IIS:
ASP.NET建立處理請求的環境。換句話說,建立應用程式對象、request、response和context對象去處理請求。
一旦環境已經建立,請求通過使用modules、handlers和page對象的一系列事件處理。為了簡化可以稱為MHPM(module、handler、page、module event),我們将在後面詳細讨論。
<a href="http://images.cnblogs.com/cnblogs_com/skynet/WindowsLiveWriter/NETCInternalsASP.NET_11CA2/1_2.jpg"></a>
圖1、ASP.NET請求處理的兩個步驟
在接下來的各節,我們将知道更多關于這兩個步驟的細節。
step 1:使用者發送一個請求到IIS。IIS首先檢查哪個ISAPI擴充可以處理這個請求,這取決于請求的檔案擴充名。舉例來說,如果請求頁面是‘.ASPX’,它将被傳送到‘aspnet_isapi.dll’來處理。
step 2:如果這是www站點的第一個請求,ApplicationManager類将建立一個應用程式域,www站點運作于其中。我們都知道在同一個IIS上,兩個web應用程式的應用程式域是獨立的(隔離的)。是以一個應用程式域中問題不會的影響到其它應用程式域。
step 3:建立的應用程式域建立宿主環境,如HttpRuntime對象。一旦宿主環境被建立,必要的ASP.NET核心對象如HttpContext、HttpRequest和HttpRespone對象也被建立。
step 4:一旦所有的ASP.NET核心對象被建立,HttpApplication對象将被建立去處理請求。如果系統中有global.asax檔案,global.asax檔案對象将被建立。請注意:global.asax檔案繼承自HttpApplication類。
注意:第一次ASP.NET頁面連接配接到應用程式,一個HttpApplication新執行個體将被建立。為了最大化性能,HttpApplication執行個體可能被多個請求重用。
step 5:接下來HttpApplication對象配置設定給核心ASP.NET對象來處理頁面。
<a href="http://images.cnblogs.com/cnblogs_com/skynet/WindowsLiveWriter/NETCInternalsASP.NET_11CA2/2_2.jpg"></a>
圖2、建立ASP.NET環境
下圖解釋了ASP.NET請求的内部對象模型。最高層是ASP.NET運作時,它已經建立一個應用程式域(AppDomain),相應地有HttpRuntime包括request、respone、context對象。
一旦建立了HttpApplication,它開始處理請求,它經曆3個不同的部分HttpModule、Page、HttpHandler。随着它移動到這些部分,将調用不同的事件,開發人員可以擴充和定制同一邏輯。在我們前進之前讓我們了解什麼是HttpModule和HttpHandlers。他們幫組我們在ASP.NET頁處理的前後注入自定義邏輯。他們之間的主要差别是:
如果你想要注入的邏輯是基于像‘.ASPX’、‘.HTML’這樣的檔案擴充名,使用HttpHandler。換句話說HttpHandler是基于處理器的擴充。
<a href="http://images.cnblogs.com/cnblogs_com/skynet/WindowsLiveWriter/NETCInternalsASP.NET_11CA2/4_2.jpg"></a>
如果你想在ASP.NET管道事件中注入邏輯,使用HttpModule。換言之是基于處理器的事件。
<a href="http://images.cnblogs.com/cnblogs_com/skynet/WindowsLiveWriter/NETCInternalsASP.NET_11CA2/5_2.jpg"></a>
Step 1(M HttpModule):用戶端請求處理開始。ASP.NET引擎開始和建立HttpModule發出事件(你可以注入定制邏輯)之前,有6個重要事件你可以使用:BeginRequest、AuthenticateRequest、AuthorizeRequest、ResolveRequestCache、AcquireRequestState和PreRequestHandlerExecute。
Step 2(H HttpHandler):一旦上面6個事件觸發,ASP.NET引擎将調用ProcessRequest事件,即使你已經在項目中執行了HttpHandler。
Step 3(P ASP.NET page):一旦HttpHandler邏輯執行,ASP.NET page對象被建立。ASP.NET page對象被建立,許多事件被觸發,你可以在這些頁面事件中寫我們自定義的邏輯。有6個重要事件給我們提供占位,在ASP.NET頁中寫邏輯:Init、Load、Validate、Event、Render、Unload。你可以記住單詞SILVER來記這些事件,S-Start(沒有任何意義,僅僅是為了形成一個單詞),I(Init)、L(Load)、V(Validate)、E(Event)、R(Render)。
Step 4(M HttpModule):一旦頁面對象執行了且從記憶體中解除安裝,HttpModule提供發送頁面執行事件,它們可用于注入自定義post-處理邏輯。有4個重要的post-處理事件,PostRequestHandlerExecute、PostRequestState、UpdateRequestCache、EndRequest。
下圖展示了上面的過程。
<a href="http://images.cnblogs.com/cnblogs_com/skynet/WindowsLiveWriter/NETCInternalsASP.NET_11CA2/6_2.jpg"></a>
下面的表格展示了什麼事件中做什麼邏輯或代碼。
Section Event Description
HttpModule BeginRequest 此事件标志着一個新的請求,他保證在每個請求中都有。
HttpModule AuthenticateRequest 此事件标志ASP.NET運作時準備驗證使用者。任何身份驗證代碼都可以在此注入。
HttpModule AuthorizeRequest 此事件标志ASP.NET運作時準備授權使用者。任何授權代碼都可以在此注入。
HttpModule ResolveRequest 在ASP.NET中我們通常使用OutputCache指令做緩存。在這個事件中,ASP.NET運作時确定是否能夠從緩存中加載頁面,而不是從頭開始生成。任何緩存的具體活動可以被注入這裡。
HttpModule AcquireRequestState 此事件标志着ASP.NET運作時準備獲得會話變量。可以對會話變量做任何你想要的處理。
HttpModule PreRequestHandlerExecute 恰好在ASP.NET 開始執行事件處理程式前發生。可以預處理你想做的事。
HttpHandler ProcessRequest HttpHandler邏輯被執行。在這個部分我們将為每個頁面擴充名寫需要的邏輯。
Page Init 此事件發生在ASP.NET頁面且可以用來:
1、動态地建立控件,如果你一定要在運作時建立控件;
2、任何初始化設定
3、母版頁及其設定
在這部分中我們沒有獲得viewstate、postedvalues及已經初始化的控件。
Page Load 在這部分ASP.NET控件完全被加載且在這裡你可以寫UI操作邏輯或任何其他邏輯。
Page Validate 如果在頁面上你有驗證器,你同樣想在這裡檢查。
Page Render 是時候将輸入發送到浏覽器。如果你想對最終的HTML做些修改,你可以在這裡輸入你的HTML邏輯。
Page Unload 頁面對象從記憶體中解除安裝。
HttpModule PostRequestHandlerExecute 可以注入任何你想要的邏輯,在處理程式執行之後。
HttpModule ReleaseRequestState 想儲存更新某些狀态變量,如會話變量。
HttpModule UpdateRequestCache 在結束之前是否更新你的緩存。
HttpModule EndRequest 這是将輸出發送到用戶端浏覽器之前的最後一個階段。
下面是HttpHandler的代碼片段,它跟蹤ProcessRequest事件。
我們也追蹤ASP.NET頁面的所有事件。
下面顯示上面讨論的所有事件的執行順序:
<a href="http://images.cnblogs.com/cnblogs_com/skynet/WindowsLiveWriter/NETCInternalsASP.NET_11CA2/7_2.jpg"></a>
在前面部分我們已經知道ASP.NET頁面請求的整體事件流,但是我們沒有詳細讨論,是以本節我們将深入了解。任何ASP.NET頁面有2個部分,
一個是顯示在浏覽器上的頁面,它有HTML标記、viewstate形式的隐藏值、HTML
inputs上的資料。當頁面被發送時,在伺服器上這些HTML标記被建立到ASP.NET控件且viewstate和表單資料捆綁在一起。一旦你得到這
些伺服器控件的背景代碼,你可以執行和寫你自己的邏輯和呈現傳回給浏覽器。
注意:大部分開發者直接使用Page_Load方法執行一切,這不是一個好的方法。是以,不是填充控件、設定viewstate、應用主題等一切都發生在頁面加載上。是以,如果我們能在适當的事件中放入邏輯,将真正使你的代碼幹淨。
Seq
Events
控件初始化
Viewstate可用
表單資料可用
什麼邏輯可以寫在這裡?
1
Init
No
注意:你可以通過使用ASP.NET請求對象通路表單資料等,但是不是通過伺服器控件。
動态地建立控件,如果你一定要在運作時建立;任何初始化設定;母版頁及其設定。在這部分中我們沒有獲得viewstate、postedvalues及已經初始化的控件。
2
Load View State
Not guaranteed
Yes
你可以通路View State及任何同步邏輯,你希望viewstate被推倒背景代碼變量可以在這裡完成。
3
PostBackdata
捏可以通路表單資料。任何邏輯,你希望表單資料被推倒背景代碼變量可以在這裡完成。
4
Load
在這裡你可以放入任何你想操作控件的邏輯,如從資料庫填充combox、對grid中的資料排序等。這個事件,我們可以通路所有控件、viewstate、發送的值。
5
Validate
如果你的頁面有驗證器或者你想為你的頁面執行驗證,那就在這裡做吧。
6
Event
如果這是通過點選按鈕或下拉清單的改變的一個回發,相關的事件将被觸發。與事件相關的任何邏輯都可以在這裡執行。
7
Pre-render
如果你想對UI對象做最終的修改,如改變屬性結構或屬性值,在這些控件儲存到ViewState之前。
8
Save ViewState
一旦對伺服器控件的所有修改完成,可以儲存控件資料到View State。
9
Render
如果你想添加一些自定義HTML到輸出,可以在這裡完成。
10
Unload
做任何你想做的清理工作。
<a href="http://images.cnblogs.com/cnblogs_com/skynet/WindowsLiveWriter/NETCInternalsASP.NET_11CA2/9_2.jpg"></a>