ASP.NET 頁面處理請求經歷一系列決定性事件,理解其順序與各階段可用資源,是撰寫高效能、無 Bug 程式碼的基礎。
| 階段 | 事件/方法 | 是否 Postback 執行 | 關鍵特性與可用資源 |
|---|---|---|---|
| 初始化 | 建構函式 (Constructor) | 每次 | 最早期;可用 HttpContext (QueryString, Form, Cookies, Cache);**不可用 Session** |
| AddParsedSubObject | 每次 | 建構控制項樹;高階頁面模板常覆寫 | |
| DeterminePostBackMode | 每次 | 決定 IsPostBack 值;可強制指定 Postback/非 Postback (罕用) | |
| OnInit (Init 事件) | 每次 | **所有宣告式控制項初始化完成**;ViewState/Postback 資料**尚未**回填;**動態建立控制項的最佳時機** | |
| 狀態還原 | LoadPageStateFromPersistenceMedium | 僅 Postback | 從持久媒介 (預設隱藏欄位) 載入 ViewState 原始資料;可覆寫自訂儲存 (Session、資料庫) |
| LoadViewState | 僅 Postback | 遞迴還原 ViewState 至頁面/控制項;動態控制項**必須在 OnInit 已建立**才能正確還原 | |
| ProcessPostData (第一次) | 僅 Postback | 私有方法;依控制項 Name 比對回填使用者輸入值 (IPostBackDataHandler);**動態控制項必須在此前建立** | |
| OnLoad (Load 事件) | 每次 | **最常用**;所有值 (ViewState + Postback) 已完整還原;判斷 IsPostBack 決定是否重新繫結資料;可呼叫 Validate()/檢查 IsValid | |
| 事件處理 | ProcessPostData (第二次) | 僅 Postback | 處理 OnLoad 中動態新增控制項的 Postback 資料;在此後建立的控制項無法接收 Postback 值、不觸發 Changed 事件 |
| RaiseChangedEvents | 僅 Postback | 觸發值變更事件 (TextChanged, SelectedIndexChanged 等);順序不保證 | |
| RaisePostBackEvent | 僅 Postback | 觸發按鈕 Click、Command 等 Postback 事件 (IPostBackEventHandler);Validate() 若未手動呼叫則自動執行 | |
| 預渲染 | OnPreRender (PreRender 事件) | 每次 | **輸出前最後修改頁面/控制項的機會**;動態控制項仍可建立 (會追上 ViewState,但無 Postback 值/事件);IE Bug 導致事件遺失時的補救點 |
| 儲存狀態 | SaveViewState | 每次 | 將 ViewState 序列化;此後設定 Attributes/Style 不會進 ViewState |
| 渲染 | Render / RenderControl | 每次 | 產生 HTML 輸出;不可修改控制項樹結構 |
| 釋放 | Unload / Dispose | 每次 | 清理資源;回應已發送,不可再修改 Response |
DeterminePostBackMode 後確定,OnLoad 時已可靠使用。OnLoad 後、RaisePostBackEvent 前自動執行 (若未手動呼叫);驗證控制項需在此前加入控制項樹。Protected Overrides Sub OnInit(e As EventArgs)
Trace.Write("Lifecycle", "OnInit")
MyBase.OnInit(e)
End Sub
Protected Overrides Sub LoadViewState(savedState As Object)
Trace.Write("Lifecycle", "LoadViewState")
MyBase.LoadViewState(savedState)
End Sub
Protected Overrides Sub OnLoad(e As EventArgs)
Trace.Write("Lifecycle", "OnLoad - IsPostBack: " & IsPostBack)
MyBase.OnLoad(e)
End Sub
Protected Overrides Sub OnPreRender(e As EventArgs)
Trace.Write("Lifecycle", "OnPreRender")
MyBase.OnPreRender(e)
End Sub
Protected Overrides Sub SaveViewState() As Object
Trace.Write("Lifecycle", "SaveViewState")
Return MyBase.SaveViewState()
End Sub
Protected Overrides Sub Render(writer As HtmlTextWriter)
Trace.Write("Lifecycle", "Render")
MyBase.Render(writer)
End Sub
啟用頁面追蹤 (Trace="true") 即可在頁底看到完整執行順序與時間戳。
| 症狀 | 可能原因 | 對應生命週期階段 |
|---|---|---|
| 動態控制項 Postback 後消失/事件不觸發 | 建立時機晚於 OnInit / LoadViewState | 初始化 / 狀態還原 |
| TextBox 輸入值 Postback 後消失 | 控制項 ID 不固定 / 命名容器變更 | ProcessPostData |
| GridView 分頁/排序不生效 | 未在 IsPostBack 判斷外重新 DataBind | OnLoad |
| 驗證控制項不顯示錯誤訊息 | Validate() 呼叫時機錯誤 / 驗證群組未設定 | RaisePostBackEvent |
| PreRender 修改控制項屬性不生效 | 控制項已在 Render 階段輸出 | 渲染 |
ASP.NET 頁面生命週期嚴格遵循「初始化 → 狀態還原 → 載入 → 事件處理 → 預渲染 → 儲存狀態 → 渲染 → 釋放」順序。掌握各階段的職責邊界、資料可用性、動態控制項建立死線,是從「能跑」進化到「穩定、高效、可維護」的關鍵。建議開發者熟記上述時序表,並在遇到狀態、事件、資料繫結異常時,對照生命週期定位問題根因。