天天看點

.NET (C#) Internals: ASP.NET 應用程式與頁面生命周期(意譯)

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>

繼續閱讀