ASP.NET 頁面物件模型

來源:互聯網
上載者:User
對由 Microsoft Internet 資訊服務 (IIS) 處理的 Microsoft ASP.NET 頁面的每個請求都會被移交到 ASP.NET HTTP 管道。HTTP 管道由一系列託管對象組成,這些託管對象按順序處理請求,並將 URL 轉換為純 HTML 文本。HTTP 管道的入口是 HttpRuntime 類。ASP.NET 結構為輔助進程中的每個 AppDomain 建立一個此類的執行個體。(請注意,輔助進程為每個當前正在啟動並執行 ASP.NET 應用程式維護一個特定的 AppDomain。)

HttpRuntime 類從內部池中擷取 HttpApplication 對象,並安排此對象來處理請求。HTTP 應用程式管理器完成的主要任務就是找到將真正處理請求的類。當請求 .aspx 資源時,處理常式就是頁面處理常式,即從 Page 繼承的類的執行個體。資源類型和處理常式類型之間的關聯關係儲存在應用程式的設定檔中。更確切地說,預設的映射集是在 machine.config 檔案的 <httpHandlers> 部分定義的。但是,應用程式可以在本地的 web.config 檔案中自訂自己的 HTTP 處理常式列表。以下這一行代碼就是用來為 .aspx 資源定義 HTTP 處理常式的。

<add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory"/>

副檔名可以與處理常式類相關聯,並且更多是與處理常式工廠類相關聯。在所有情況下,負責處理請求的 HttpApplication 對象都會獲得一個實現 IHttpHandler 介面的對象。如果根據 HTTP 處理常式來解析關聯的資源/類,則返回的類將直接實現介面。如果資源被綁定到處理常式工廠,則還需要額外的步驟。處理常式工廠類實現 IHttpHandlerFactory 介面,此介面的 GetHandler 方法將返回一個基於 IHttpHandler 的對象。

HTTP 運行時是如何結束這個迴圈並處理頁面請求的?ProcessRequest 方法在 IHttpHandler 介面中非常重要。通過對代表被請求頁面的對象調用此方法,ASP.NET 結構會啟動將產生瀏覽器輸出的進程。

真正的 Page 類

特定頁面的 HTTP 處理常式類型取決於 URL。首次調用 URL 時,將構建一個新的類,這個類被動態編譯為一個程式集。檢查 .aspx 資源的分析進程的結果是類的原始碼。該類被定義為命名空間 ASP 的組成部分,並且被賦予了一個類比原始 URL 的名稱。例如,如果 URL 的終點是 page.aspx,則類的名稱就是 ASP.Page_aspx。不過,類的名稱可以通過編程方式來控制,方法是在 @Page 指令中設定 ClassName 屬性。

HTTP 處理常式的基類是 Page。這個類定義了由所有頁面處理常式共用的方法和屬性的最小集合。Page 類實現 IHttpHandler 介面。

在很多情況下,實際處理常式的基類並不是 Page,而是其他的類。例如,如果使用了代碼分離,就會出現這種情況。代碼分離是一項開發技術,它可以將頁面所需的代碼隔離到單獨的 C# 和 Microsoft Visual Basic .NET 類中。頁面的代碼是一組事件處理常式和輔助方法,這些處理常式和方法真正決定了頁面的行為。可以使用 <script runat=server> 標記對此代碼進行內聯定義,或者將其放置在外部類(代碼分離類)中。代碼分離類是從 Page 繼承並使用額外的方法的類,被指定用作 HTTP 處理常式的基類。

還有一種情況,HTTP 處理常式也不是基於 Page 的,即在應用程式設定檔的 <pages> 部分中,包含了 PageBaseType 屬性的重新定義。

<pages PageBaseType="Classes.MyPage, mypage" />

PageBaseType 屬性指明包含頁面處理常式的基類的類型和程式集。從 Page 匯出的這個類可以自動賦予處理常式擴充的自訂方法和屬性集。

頁面的生命週期

完全識別 HTTP 頁面處理常式類後,ASP.NET 運行時將調用處理常式的 ProcessRequest 方法來處理請求。通常情況下,無需更改此方法的實現,因為它是由 Page 類提供的。

此實現將從調用為頁面構建控制項樹的 FrameworkInitialize 方法開始。FrameworkInitialize 方法是 TemplateControl 類(Page 本身從此類匯出)的一個受保護的虛擬成員。所有為 .aspx 資源動態產生的處理常式都將覆蓋 FrameworkInitialize。在此方法中,構建了頁面的整個控制項樹。

接下來,ProcessRequest 使頁面經曆了各個階段:初始化、載入檢視狀態資訊和回傳資料、載入頁面的使用者代碼以及執行回傳伺服器端事件。之後,頁面進入顯示模式:收集更新的檢視狀態,產生 HTML 程式碼並隨後將代碼發送到輸出控制台。最後,卸載頁面,並認為請求處理完畢。

在各個階段中,頁面會觸發少數幾個事件,這些事件可以由 Web 控制項和使用者定義的代碼截取並進行處理。其中的一些事件是嵌入式控制項專用的,因此無法在 .aspx 代碼級進行處理。

要處理特定事件的頁面應該明確註冊一個適合的處理常式。不過,為了向後相容早期的 Visual Basic 編程風格,ASP.NET 也支援隱式事件掛鈎的形式。預設情況下,頁面會嘗試將特定的方法名稱與事件相匹配,如果實現匹配,則認為此方法就是匹配事件的處理常式。ASP.NET 提供了六種方法名稱的特定識別,它們是 Page_InitPage_LoadPage_DataBindPage_PreRenderPage_Unload。這些方法被認為是由 Page 類提供的相應事件的處理常式。HTTP 運行時會自動將這些方法綁定到頁面事件,這樣,開發人員就不必再編寫所需的粘接代碼了。例如,如果命名為 Page_Load 的方法綁定到頁面的 Load 事件,則可省去以下代碼。

this.Load += new EventHandler(this.Page_Load);

對特定名稱的自動識別是由 @Page 指令的 AutoEventWireup 屬性控制的。如果該屬性設定為 false,則要處理事件的所有應用程式都需要明確串連到頁面事件。不使用自動綁定事件的頁面效能會稍好一些,因為不需要額外匹配名稱與事件。請注意,所有 Microsoft Visual Studio .NET 項目都是在禁用 AutoEventWireup 屬性的情況下建立的。但是,該屬性的預設設定是 true,即 Page_Load 等方法會被識別,並被綁定到相關聯的事件。

下表中按順序列出了頁面的執行包括的幾個階段,執行的標誌是一些應用程式級的事件和/或受保護並可覆蓋的方法。

表 1:ASP.NET 頁面生命中的關鍵事件

階段 頁面事件 可覆蓋的方法
頁面初始化 Init  
載入檢視狀態   LoadViewState
處理回傳資料   任意實現 IPostBackDataHandler 介面的控制項中的 LoadPostData 方法
載入頁面 Load  
回傳更改通知   任意實現 IPostBackDataHandler 介面的控制項中的 RaisePostDataChangedEvent 方法
處理回傳事件 由控制項定義的任意回傳事件 任意實現 IPostBackDataHandler 介面的控制項中的 RaisePostBackEvent 方法
頁面顯示前階段 PreRender  
儲存檢視狀態   SaveViewState
顯示頁面   Render
卸載頁面 Unload  

以上所列的階段中有些在頁面級是不可見的,並且僅對伺服器控制項的編寫者和要建立從 Page 匯出的類的開發人員有意義。InitLoadPreRenderUnload,再加上由嵌入式控制項定義的所有回傳事件,就構成了向外發送頁面的各個階區段標記。

執行的各個階段

頁面生命週期中的第一個階段是初始化。這個階段的標誌是 Init 事件。在成功建立頁面的控制項樹後,將對應用程式觸發此事件。換句話說,當 Init 事件發生時,.aspx 源檔案中靜態聲明的所有控制項都已執行個體化並採用各自的預設值。控制項可以截取 Init 事件以初始化在傳入的 Web 請求的生命週期內所需的所有設定。例如,這時控制項可以載入外部模板檔案或設定事件的處理常式。請注意,這時檢視狀態資訊尚不可用。

初始化之後,頁面架構將載入頁面的檢視狀態。檢視狀態是成對的名稱和數值的集合,在此集合中,控制項和頁面本身儲存了對所有 Web 請求都必須始終有效全部資訊。檢視狀態代表了頁面的調用上下文。通常,它包含上次在伺服器上處理頁面時控制項的狀態。首次在會話中請求頁面時,檢視狀態為空白。預設情況下,檢視狀態儲存在靜默添加到頁面的隱藏欄位中,該欄位的名稱是 __VIEWSTATE。通過覆蓋 LoadViewState 方法(Control 類的受保護、可覆蓋方法),組件開發人員可以控制檢視狀態的儲存方式以及檢視狀態的內容映射到內部狀態的方式。

有些方法(如 LoadPageStateFromPersistenceMedium 以及其對應的 SavePageStateToPersistenceMedium),可以用來將檢視狀態載入並儲存到其他儲存介質(例如會話、資料庫或伺服器端檔案)中。與 LoadViewState 不同,上述方法只能在從 Page 匯出的類中使用。

儲存檢視狀態之後,頁面樹中控制項的狀態與頁面最後一次顯示在瀏覽器中的狀態相同。下一步是更新它們的狀態以加入用戶端的更改。處理回傳資料階段使控制項有機會更新其狀態,從而準確反映用戶端相應的 HTML 元素的狀態。例如,伺服器的 TextBox 控制項對應的 HTML 元素是 <input type=text>。在回傳資料階段,TextBox 控制項將檢索 <input> 標記的當前值,並使用該值來重新整理自己內部的狀態。每個控制項都要從回傳的資料中提取值並更新自己的部分屬性。TextBox 控制項將更新它的 Text 屬性,而 CheckBox 控制項將重新整理它的 Checked 屬性。伺服器控制項和 HTML 元素的對應關係可以通過二者的 ID 找到。

在處理回傳資料階段的最後,頁面中的所有控制項的狀態都將使用用戶端輸入的更改來更新前一狀態。這時,將對頁面觸發 Load 事件。

頁面中可能會有一些控制項,當其某個敏感屬性在兩個不同的請求中被修改時,需要完成特定的任務。例如,如果 TextBox 控制項的文本在用戶端被修改,則此控制項將觸發 TextChanged 事件。每個控制項在其一個或多個屬性被修改為用戶端輸入的值時都可以決定觸發相應的事件。對於這些更改對其非常關鍵的控制項,控制項實現 IPostBackDataHandler 介面,此介面的 LoadPostData 方法是在 Load 事件後立即調用的。通過對 LoadPostData 方法進行編碼,控制項將驗證自上次請求後是否發生了關鍵更改,並觸發自己的變更事件。

頁面生命週期中的關鍵事件是被調用以執行伺服器端代碼的事件,此代碼與用戶端觸發的事件相關聯。當使用者單擊按鈕時,將回傳頁面。回傳值的集合中包括啟動整個操作的按鈕的 ID。如果控制項實現 IPostBackEventHandler 介面(如按鈕和連結按鈕),頁面架構將調用 RaisePostBackEvent 方法。此方法的行為取決於控制項的類型。就按鈕和連結按鈕而言,此方法將尋找 Click 事件處理常式並運行相關的委託。

處理完回傳事件之後,頁面就可以顯示了。這個階段的標誌是 PreRender 事件。控制項可以利用這段時間來執行那些需要在儲存檢視狀態和顯示輸出的前一刻執行的更新操作。下一個狀態是 SaveViewState,在此狀態中,所有控制項和頁面本身都將更新自己 ViewState 集合的內容。然後,將得到序列化、散列、Base 64 編碼的檢視狀態,而且此檢視狀態與隱藏欄位 __VIEWSTATE 相關聯。

通過覆蓋 Render 方法可以改變各個控制項的顯示機制。此方法接受 HTML 書寫器對象,並使用此對象來積累所有要為控制項產生的 HTML 文本。Page 類的 Render 方法的預設實現包括對所有成員控制項的遞迴調用。對於每個控制項,頁面都將調用 Render 方法,並緩衝 HTML 輸出。

頁面生命中的最後一個標誌是 Unload 事件,在頁面對象消除之前發生。在此事件中,您應該釋放所有可能佔用的關鍵資源(例如檔案、繪圖物件、資料庫連接等)。

在此事件之後,也就是最後,瀏覽器接收 HTTP 響應資料包並顯示頁面。

小結

ASP.NET 頁面物件模型因其事件機制而顯得格外新穎獨特。Web 頁面由控制群組成,這些控制項既可以產生豐富的基於 HTML 的使用者介面,又可以通過事件與使用者互動。以前,在 Web 應用程式的上下文中設定事件模型是件有挑戰性的工作。可我們驚奇的看到,用戶端產生的事件可以由伺服器端的代碼來解決,而且只進行一些相應的修改後,此過程仍可以輸出相同的 HTML 頁面。

掌握這個模型對於瞭解頁面生命週期的各個階段,以及頁面對象如何被 HTTP 運行時執行個體化並使用是非常重要的。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.