-
前言
百度了一下才知道,傳智的鄒老師桃李滿天下呀,我也是鄒老師的粉絲,最開始學習頁面生命周期的時候也是看了鄒老師的視訊。
本人是參考了以下前輩的作品,本文中也參合了本人心得,絕非有意盜版,旨在傳播,最主要是日後在下也可以參考一下,原版出處如下:
1.博友學海無涯-Asp.Net頁面生命周期
2.博友陽陽多-用三張圖檔詳解Asp.Net 全生命周期
-
概念
所謂的頁面生命周期說通俗一點,就是浏覽器有請求,伺服器處理請求并生成HTML代碼所執行的一系列的事件方法。
-
概括知識點
1.伺服器與浏覽器之間的互動:通過Scoket
2.伺服器與浏覽器互動文法:Http協定
3.伺服器與浏覽器互動目的:擷取伺服器資源(html,js,img,css..)
4.伺服器要做的事就是想盡辦法滿足浏覽器的需求,是以一旦浏覽器請求的是動态頁面的時候,伺服器就要建立頁面類對象并執行裡面的一系列的事件與方法,并将生成的html頁面代碼傳回給浏覽器.
-
頁面生命周期事件
1.PreInit:
-
- 檢查IsPostBack 屬性
- 建立或重新建立動态控件
- 動态設定主要頁
- 動态設定Theme屬性
- 讀取或者設定配置檔案屬性值
- 設定控件的預設值(UniqueId等)
- 動态設定Master Page
注意:如果請求是回發請求,剛控件的值尚未從視圖狀态還原,如果在此階段設定控件屬性,則其值可能會在下一事件中被重寫。
2. Init:
在所有控件都已經初始化且已應用所有外觀設定後引發,使用該事件來讀取或初始化控件屬性
3.InitComplete:
由Page對象引發。使用該事件來處理要求先完成所有初始化工作的任務。
4.PreLoad:
如果需要在Load事件之前對頁或者控件執行處理,則使用該事件。
在Page引發該事件後,它會為自身和所有 控件加載視圖狀态,然後會處理Request執行個體包括的任何回發資料。
5.Load:
在Page上調用OnLoad事件方法,然後以遞歸方式對每個子控件執行相同操作,如此循環往複,直到加載完頁面和所有控件為止
6.控件事件:
使用這些事件來處理特定控件事件,如Button控件的Click事件或TextBox控件的TextChanged事件
注意:在回發請求中,如果頁包含驗證程式控件,剛需要在執行任何處理之前檢查Page和各個驗證控件的IsValid屬性
7.LoadComplete:
對需要加載頁上的所有其他控件的任務使用該事件
8.PreRender:
在該事件發生之前:
-
- Page對象會針對每個控件和頁調用 EnsureChildControls
- 設定了DataSourceID屬性的每個資料綁定控件會調用DataBind方法
頁上的每個控件都會發生PreRender事件。使用該事件對頁或其控件的内容進行最後更改
9.SaveStateComplete
在該事件發生前,已對每個控件儲存了ViewState。将忽略此時對頁或控件進行的任何更改。使用該事件執行滿足以下條件的任務:要求已經儲存了視圖狀态,但未對控件進行任何更改。
10.Render
這不是事件:在處理的這個階段,Page對象會在每個控件上調用此方法。所有 ASP.NET Web伺服器控件都有一個用于寫出發送給浏覽器的控件标記的Render方法。如果建立自定義控件,則通常要重寫此方法以輸出控件的标記。不過如果自定義控件隻合并标準的 ASP.NET Web伺服器控件,并不合并自定義标記,則不需要重寫Render方法。使用者控件自動合并呈現,是以不需要在代碼中顯式呈現該控件。
11:UnLoad
該事件首先針對每個控件發生,繼而針對該頁發生,在控件中,使用該事件對特定控件執行最後清理,如關閉控件特定資料庫連接配接,清理輸出緩存。對于頁自,使用該事件來執行最後的清理工作,如關閉打開 的檔案和資料庫連接配接,或完成日志記錄或其他特定請求任務。
-
學習目的
有些人講,webform/asp.net方面的技術,有些研究得太深,在現實開發中其實不一定有太大的價值。我極力的反駁這句話。據我個人了解與使用情況,學習頁面生命周期有以下幾個好處:
1.開發Asp.net自定義控件與使用者控件
2.利用HttpModule注冊頁面生命周期中HttpApplication中用于處理請求的19個事件管道所對外公布的一系列的事件方法
3.編寫頁面周期事件方法(如:Page_PreLoad,Page_Load,Page_Init...)等等一系列的事件,且這些方法并不會因為我們的編寫而覆寫原有的事件方法,請大家放心使用,不過在上述所有事件前面要加上Page_。
-
注意事項
1.所有控件都有生命周期,我們在前面就已經了解到Page類是繼承Control類的,而我們所有的伺服器控件也都是繼承Control類的
2.雖然Init與Load都在每個控件上以遞歸方式發生,但它們的發生順序相反,每個子控件的Init事件(還有UnLoad事件)在為其容器引發相應的事件之前發生(由上到下)。但是,容器的Load事件是在其子控件的Load事件之前 發生(由上到下)的。
3.從Page類繼承過來的時候,除了可以處理由頁引發的事件以外,還可以重寫頁的基類中的方法,例如可以重寫頁的InitializeCulture方法,以便動态設定區域性資訊,注意,在使用Page_事件文法建立事件處理程式時,将隐式調用基實作,是以無須在方法中調用它。例如使用Page_Load方法始終會調用基類的OnLoad方法,如果使用overrider重寫了頁的OnLoad方法,則必須顯式調用基類的OnLoad方法,如base.OnLoad()以運作基實作。
-
浏覽器與伺服器的通信過程
通信過程:
當伺服器運作正常的情況下,用戶端(浏覽器) 向伺服器端發送請求時,伺服器端負責監聽的套接字(socket),監聽到有連接配接請求後,會為該用戶端建立一個用于通信的套接字與用戶端進行通信。當使用者在浏覽器向伺服器發送請求時,浏覽器會按照雙方都約定好的網絡傳輸層http協定,将請求轉換成符合Http協定的請求封包。然後通過裝置按照TCP協定發送到伺服器。在伺服器端接收到請求封包後。會按照Http協定對封包進行解析。若請求的内容為靜态的資料,伺服器端直接将被請求的資料,按照Http協定生成響應封包後傳回給浏覽器。浏覽器然後解析收到的封包。将頁面顯示到浏覽器視窗。(注:最開始僅是顯示一個html 架構。經過多次請求。将CSS樣式,圖檔………逐一的加載進來形成一個完整的頁面。這個過程,有多次的互動通信。當通信結束後會把用來通信的套接字銷毀,因為http協定是一種無狀态的通信。這樣減輕了伺服器的壓力)
當浏覽器向用戶端發送的請求為動态的。那麼伺服器(IIS)發現處理不了這種字尾名的檔案時,會通過映射表到。響應實作了接口的可擴充程式asp.net_isapi.dll, 然後asp.net_isapi.dll,又将請求轉交給網站程式處理.網站程式調用
httpRuntime類的processRequest方法來處理:
1.此類會分析接收到的請求封包.将請求封包封裝到名稱為httpWorkerRequest的類的屬性中(便于其它地方以用).
2.建立HttpContext對象.這個對象是目前所請求封包的上下文環境.它包含了所有的請求資料.其中有兩個最重要類的對象:http.Request和http.Response. 在httpRequest對象中又包含了兩個屬性.Form(通過表單請求的資料參數).Querystring(通過URL傳遞的資料參數); 通過索引器,可以找到參數的值. 在httpResponse 對象中有一個TextWriter對象.在它裡面儲存的是被請求的頁面在執行過程中要向浏覽器輸出的資料.可以通過write 方法對其進行輸出給浏覽器。
3.通過HttpApplicationFactory類的的一個靜态方法。來為每個請求建立一個單獨的httpApplication對象。在建立之前HttpApplicationFactor會到HttpApplication池中檢視,有沒有空閑的。若有直接用。沒有的時候才建立新的HttpApplication。
4.在httpApplication裡運作己轉換成接口IhttpHandler 的通過反射被請求頁面對象的ProcessRequest 方法.
方法執行過程如下:先執行httpApplication中的processRequest方法。在此方法中包含了要按照先後順序執行的19個委托事件 當在執行到第8個事件(PostMapRequestHandler)的時候就開始建立被請求頁面對象,并得到請求處理程式,在執行到第11個事件(PreRequestHandlerExecute)後。就執行被建立的請求頁面對象的ProcessRequest方法。
-
HttpApplication 通信管理(用于給HttpModule注冊使用的19個事件委托)
HttpModule被稱為Filter過濾器。使用者可以利用HttpModule來給這19個委托事件來注冊方法,完成需求,比如說可以在AcquireRequestState中驗證是否登入呀,權限驗證等
詳情請檢視:HttpModule實作使用者身份驗證
如果不清楚HttpModule可以檢視:HttpModule的認識
-
頁面生命周期詳細過程
其實頁面生命周期裡面還有很東西,如PageHandlerFactory等等這些東東也夠吃一壺的,發現我每走到一個領域,發現我要學的東西實在是太多太多啦,總感覺自己所學的東西隻是滄海一粟,走過了這道坎,又是一片海洋,我隻能呐喊:生命永不止息,學海無涯。
海闊平魚躍,天高任我行,給我一片藍天,讓我自由翺翔。