介紹
每當請求IIS容納的ASPNET頁時總是要把請求轉交給了ASPNET HTTP 管道HTTP管道是一組被控對象這些對象按順序處理請求並且把這些請求轉換成一般HTML文本HTTP管道的入口是HttpRuntime 類ASPNET的底層結構為每一個應用程序域 ( AppDomain )的工作進程建立了一個這個類(HttpRuntime)的實例(注意一個工作進程只能支持一個正在運行的ASPNET應用域)
HttpRuntime 類從內部程序池中選擇一個 HttpApplcation 對象並且在接收到請求的時候使它工作Http應用管理程序的主要工作是尋找這樣的類使之能夠處理請求例如當請求一個aspx資源時處理句柄就是一個從Page繼承類的實例請求資源的類型和相關處理句柄的關系映射表被保存在應用程序的配置文件裡更確切的說這個映射表就定義在nfig裡的<httpHandlers>一節裡但是應用程序能在nfig裡對這個HTTP處理句柄映射列表進行重定義下面這行語句說明了定義aspx資源請求的處理句柄
<add verb=* path=*aspx type=SystemWebUIPageHandlerFactroy/>
一個擴展可以和一個句柄類聯系起來更一般說是和一個句柄工廠類相聯系在所有情況下負責處理請求的HttpApplication對象得到一個從IHttpHandler接口具體實現的對象如果是根據HTTP句柄來處理資源和相關處理類的關系則返回類是直接實現相關的接口的如果資源是綁定到一個句柄工廠的話將必須經過另外一個階段具體實現IHttpHandlerFactory接口的句柄工廠類的GetHandler方法將返回一個基於IHttpHandler的對象
Http運行時怎麼結束一個周期或關閉一個頁面請求的進程呢?IHttpHandler接口的ProcessRequest方法擁有這個功能調用代表被請求頁面的對象的該方法ASPNET底層結構打開一個進程來為浏覽器產生輸出
Page類
一個頁面的HTTP處理句柄的類型取決於URL當這個URL被首次訪問一個新的類將被構建並動態的編譯成一個程序集一個分析aspx文件的進程從aspx文件中分離出這個類的代碼在默認情況下這個類被加入到一個叫做asp的名字空間裡並且把URL作為這個類的類名例如如果請求的URL是pageaspx則這個類就是ASPPage_aspx這個類名可以通過設置@Page預處理指令的ClassName屬性來修改
HTTP句柄的基礎類是Page類這個類定義了一組最小方法和屬性集這些方法和屬性被所有的頁面處理句柄所共享Page類具體實現了IHttpHandler接口
在另外一種和上述相對應的情況中實際處理頁面的句柄的基礎類並不是Page類而是一個別的類當使用後代碼模式時這個情況就發生了後代碼是一種將C#或VBNET代碼和頁面分離的技術頁面代碼是一組事件處理句柄和其他一些方法的集合這些方法定義了頁面的各種行為這些代碼可以以內聯形式用<script runat=server>標簽定義或者你可以用外部類形式來寫——這就是後代碼模式後代碼類是從Page類繼承的但是具體化或者重新定義了一些其他的方法在指定了頁面的後代碼類後這個後代碼類就作為HTTP處理句柄
在其他的情況下如果應用程序的配置文件中重定義了<pages>節的PageBaseType屬性則HTTP處理句柄不是基於Page類的例如
<pages PageBaseType = ClassesMyOage mypage />
PageBaseType屬性指明了包含頁面處理句柄父類的類型和程序集來自Page類的這些類自動賦予一些通常或擴展的方法和屬性的集合給處理句柄
頁面生命周期
一旦HTTP頁面處理句柄被明確的定義了ASPNET運行時調用處理句柄的ProcessRequest方法來處理請求通常沒有必要改變Page類提供的執行方法
頁面執行是從FrameworkInitialize方法開始的這個方法為頁面構建控件樹該方法是TemplageControl類的受保護並且是虛方法任何為aspx資源動態生成的句柄覆蓋了該方法在這個方法裡頁面的所有控件樹都被構建了
接下來ProcessRequest方法使頁面經歷了不同的幾個階段初始化加載視圖狀態信息回傳數據加載頁面代碼和執行回傳的服務器事件在這之後頁面轉換到了顯示模式收集被更新的視圖狀態產生HTML代碼並且傳送到控制台最後頁面卸載請求的全部服務結束了
在各個不同階段裡頁面處理了與web控件相關程序員代碼能夠干預並解決一定問題的事件其間一些事件是專門為那些內嵌控件和不能在aspx代碼級別處理的控件而設計的
一個頁面要解決這樣的事件它能明確的注冊成為合適的句柄但是為了和原有的Visual Basic編程模式有後向兼容性ASPNET也支持了隱含事件的形式在默認情況下頁面會尋找和事件相關的方法名如果找到和事件相匹配的方法這個方法就被認為是這種事件的處理程序ASPNET提供了六種專門的方法名他們是 Page_Init Page_Load Page_DataBind Page_PreRender 和 Page_Unload 這些方法這些方法在Page類中已經被定義過他們是相應事件的處理程序HTTP運行時將自動的將這些方法綁定到相關的頁面事件而不需要程序員去編寫把事件和方法聯系起來的代碼舉個例子來說在下面的代碼中 Page_Load方法和頁面的加載事件相關聯
thisLoad + = new EventHandler(thisPage_Load);
這種自動識別是被 @Page 預指令的AutoEventWireup 屬性控制的如果這個屬性被置false 應用程序必須顯式聲明和事件相關的方法不自動關聯頁面事件代碼的頁面執行起來會快一些是因為他們不需要在匹配上做過多的工作在Visual StudioNET 工程裡可以把這個屬性關閉掉但是默認設置是true這意味著Page_Load方法被自動識別並被關聯到相關的事件
頁面執行包含了下表中按順序列出的幾個階段他們被標志成為應用程序級別的事件同時也可能是一些受保護重定義的方法
階段
頁面事件
可重定義的方法
頁面初始化
Init
視圖狀態加載
LoadViewState
回傳數據處理
控件裡實現了IPostBackDataHandler接口的LoadPostData方法
頁面加載
Load
回傳數據變化檢查
控件裡實現了IPostBackDataHandler接口的RaisePostDataChangedEvent方法
回傳事件處理
控件裡定義的回傳事件
控件裡實現了IPostBackEventHandler接口的RaisePostBackEvent方法
頁面預返回階段
PreRender
頁面返回階段
Render
頁面卸載階段
Unload
上表中列出的階段有的在頁面級別是不可見的他們只是在服務器控件的作者編寫繼承於Page的類時會使用到Init Load PreRender Unload再加上定義在內嵌控件中的回傳處理事件他們構成了頁面的整個生命周期
各個階段的執行
頁面生命周期的第一階段是初始化這個階段被Init事件所描述這個事件在控件樹被構建出來後執行換句話說當Init事件發生時所有在aspx文件中靜態聲明的控件被實例化並被賦予了默認值在Init事件中可以初始化任何的在頁面生命周期裡需要的設置例如在這個階段控件可以加載外部的摸版文件或者是為事件建立處理句柄需要注意的是任何的視圖狀態信息在這個階段裡是不能用的
緊接著初始化結束後頁面構架為頁面加載視圖狀態視圖狀態是 名稱/值 對的集合控件或頁面在這裡保存的數據在整個web請求過程中必須是穩固的視圖狀態代表著頁面的上下文典型的它保存著頁面上次在服務器上被執行時控件的狀態視圖狀態在會話開始的第一個頁面請求時是空的在默認情況下試圖狀態被保存在一個隱藏域裡這個隱藏域是被自動添加到頁面裡的這個隱藏域的名稱是 __VIEWSTATE如果覆蓋了LoadViewState方法——在Control類裡被聲明為受保護的方法——組件開發者可以控制視圖狀態的保存和它是如何和內部狀態形成映射
象LoadPageStateFormPersistenceMedium這樣的方法和與其相對應的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接口(Button和LinkButton就是這樣的情況)頁面構架將調用RaisePostBackEvent方法這個方法的具體情況是取決於控件的類型的在上面提到的Button和LinkButton控件這個方法就將尋找Click事件處理程序
處理了回傳事件之後頁面就准備被發送出去了這個階段是從PreRender事件開始的這對於控件來說那些需要在視圖信息被保存與結果被發送之前這段時間裡執行的動作這是一個很好的時機下一步就是SaveViewState 所有的空間和頁面本身就把視圖狀態的集合內容保存起來接下來視圖狀態被串行化哈希編碼Base 編碼並且保存在__VIEWSTATE隱藏域裡
各個控件的發送機制可以通過重定義Render方法來改變這個方法構建了一個HTML writer對象用它來為控件產生HTML代碼對Page類裡Render方法的默認執行包含了對所有成員控件的遞歸調用頁面為每一個控件調用一次Render方法並緩沖HTML輸出
頁面生命周期的最後階段是卸載事件這個事件在頁面對象消失前被激發在這個事件裡你應該把任何臨界資源釋放掉(例如文件圖形對象數據庫連接)
最後浏覽器接收到了HTTP響應並且把頁面顯示出來
總結
ASPNET頁面對象模型是一個有特點的新穎的模型因為它是基於事件機制的一個Web頁由一些控件組成這些控件擁有豐富的基於HTML的用戶接口同時通過事件和用戶進行交互在Web應用程序上下文環境中構建一個事件模型是富有挑戰性的使客戶端產生的事件和服務器上的代碼關聯起來是令人驚異的這個過程是輸出同HTML也一樣是可見的只不過他們在需要的時候被恰當的修改
要了解頁面生命周期的各個階段頁面對象是怎樣實例化並被HTTP運行時所使用掌握這個模型是很重要的
From:http://tw.wingwit.com/Article/program/net/201311/13132.html