asp.net生命周期一直就想對他徹底的動手搞清楚了。以前一直處於朦朦朧朧的認識狀態,今天終於下狠心動手做了個例子來了解生命周期過程。之所以打算自己動手做是因為我一直覺得雖然網上有了類似的例子,不過只有自己親手做一遍然后通過博客寫出來才能使自己更深刻的理解這些內容。好了,不廢話了,開始做。
先來看一下整個項目的結構以便對我們做的例子有一個大體的了解。項目中我定義了一個module,handler,global和一個頁面以及自定義的一個控件。因為有的過程中沒法直接使用Response方法,為了記錄頁面中事件的信息我使用了Logger這個類來專門記錄信息,這是類采用了單例設計模式。來看一下他的代碼:
public class Logger { private static Logger _logger; private static object _o = new object(); public static String _tempInfo; //記錄臨時信息,頁面卸載后將被清空 public static String _showInfo; //頁面卸載時_tempInfo中的信息將被傳遞過來用於顯示 private Logger() { } public static Logger GetInstance() { lock (_o) { if (_logger != null) { return _logger; } else { _logger = new Logger(); return _logger; } } } public void WriteInfo(String info) { _tempInfo += String.Format("<p>{0}</p>",info); } public void WriteInfo(String info,string color) { _tempInfo += String.Format("<p style=\"color:{0};\">{1}</p>", color, info); } }
有了這個類我們就方便了各個過程的記錄了。下面就在各個頁面中增加記錄代碼,大概的格式樣子是這樣子的:
Logger l = Logger.GetInstance(); l.WriteInfo("Application_Start","blue");
同時為了了解自定義控件中的順序我們自定義了一個簡單的控件,它實現了IPostBackDataHandler,IPostBackEventHandler這樣就能看到控件回調引起的數據處理和事件處理了。另外自定義的module的Init方法中也被記錄了信息(代碼就不貼出來了,大家看后面的源碼,對module不了解的建議谷歌一下)。
將global和頁面里面的各個事件都記錄信息后運行程序如下:
頁面中我放了兩個自定義的控件,所以會顯示兩次。從上面的四幅圖我總結了以下幾點:
1.Application_Start是指網站重新編譯,重啟等情況下第一次被人訪問時激發。
以后所以都不會被執行到(由1,2,3副圖片對比可以看出)也就是說執行且執行一次。通常可以定義一些全局變量。
2.Session_Start是某個用戶在某個會話期中第一次訪問激發的。
如上圖第一副圖片中我們在chrome下第一次訪問頁面session_start被激發,然后再通過chrome訪問這個頁面時(第二副圖片)session_start就不被激發了。而當我們再用firefox打開這個頁面時session_start又被激發了。由此可以驗證我們的猜想。Session_Start方法通常用於設置某人的一些信息到SESSION,或觸發用戶訪問計數等
3.Application_BeginRequest,Application_BeginRequest每次請求,不管用戶是不是第一次訪問,頁面是不是回發等等。
利用這個特點一般可以在Application_BeginRequest中進行URL重寫。而Application_BeginRequest看名字也知道了,可以在其中進行權限驗證等等操作。
4.控件數據回發的流程
頁面OnInit事件中調用各個控件的LoadPostData方法加載從頁面發過來的控件值。然后在Page_Load后調用各個控件的RaisePostDataChangedEvent的事件(我們在LoadPostData人為返回了TRUE,所以該方法一定會被執行)來完成對應的數據更改事件。
5.控件事件回發觸發的時機
從第三幅圖可以看到控件是在數據回發事件后進行的。這點也可以從第二副圖看出來,Button1_click事件就在數據回發后進行的。籠統一點說就是控件的狀態更改都在page_load后進行。
6.為什么Application_BeginRequest會執行兩次?
大家也看到了,很奇怪的是我們明明就請求了一個頁面,頁面中也沒有其他的圖片請求。為什么Application_BeginRequest會被執行了兩次呢?!既然他請求,那我們看看他到底在請求什么就是了?在Application_BeginRequest代碼中將”HttpContext.Current.Request.Path”記錄顯示文件中。然后執行顯示如下:
以前也一直沒有注意到這方面的內容。原來默認回去請求網站的圖標啊。沒文化了^_^!我找了個圖片放到網站根目錄下,再次刷新瀏覽器有效果了:
7.整個頁面的執行過程
第一副圖就是最好的例子,不過感覺還是要再總結一下(可能事件有點少,不過重要的都畫出來了):
上面只是從我們的編碼能夠涉及到的地方看了下asp.net的執行流程。那么在這之前呢?就是從IIS接受到這個請求到我們上面講到的這之間的過程又是如何的呢?
借用網上的一張圖片來說明一下:IIS會首先根據請求地址的映射將其提交到aspnet_isapi.dll(具體的映射關系可以在IIS中設置),然后經過中間的一些COM組件(詳細說起來還是蠻復雜的,具體可以看這篇文章)到達ISApiRuntime,在這里請求將會被路由到ISAPIRuntime.ProcessRequest()方法里。這個方法會接着調用HttpRuntime.ProcessRequest,這個方法會為請求創建了一個新的HttpContext實例然后獲取一個HttpApplication實例並調用HttpApplication.Init()初始化管道事件。於是這樣就到了我們上面的Global.ascx定義的各個方法中。
看起來可能簡單,不過還是很復雜的。這些過程都不是我們能夠控制的,所以我覺得了解一下就可以了。真正掌握的還是上面的幾個過程。
好了,說的也差不多了。以后這上面有新的體會再補充吧。奉上測試代碼!