頁面載入時 Page_Load 被呼叫兩次,導致資料重複查詢、初始化邏輯重跑、ViewState 異常等。
@Page 指示詞缺少 AutoEventWireup="false",或顯式設為 true(預設值)。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApp.Default" %>
當 AutoEventWireup="true" 時,ASP.NET 執行階段會自動依命名慣例 (Page_Load, Page_Init 等) 將方法掛接到對應生命週期事件。
若程式碼後置 (CodeBehind) 中同時在 InitializeComponent 或建構式中手動掛接事件:
this.Load += new EventHandler(Page_Load); // 手動掛接
則會造成雙重訂閱:自動一次 + 手動一次 → Page_Load 執行兩次。
<%@ Page Language="C#" AutoEventWireup="false" CodeBehind="Default.aspx.cs" Inherits="WebApp.Default" %>
並在 InitializeComponent 或建構式中保留手動掛接:
private void InitializeComponent()
{
this.Load += new EventHandler(Page_Load);
this.Init += new EventHandler(Page_Init);
}
優點:明確控制事件訂閱、效能微幅提升、避免命名慣例衝突。
刪除 InitializeComponent 中的 this.Load += ... 等手動訂閱行,完全依賴命名慣例。
缺點:若方法命名不符慣例 (如 MyLoad) 則不會自動掛接;重構時易忘記。
protected void Page_Load(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Page_Load 執行 " + DateTime.Now.Ticks);
// 輸出視窗應只出現一次
}
| 原因 | 現象 | 排查 |
|---|---|---|
| Master Page 也有 Page_Load | 母版頁與內容頁各執行一次 | 正常生命週期,非重複 |
| UpdatePanel 觸發部分回傳 | 非同步請求也會跑 Page_Load | 檢查 IsPostBack、ScriptManager.IsInAsyncPostBack |
| Response.Redirect 同頁導向 | 完整生命週期跑兩次 | 改用 Server.Transfer 或避免導向 |
| HttpModule 重寫路徑 | 攔截器導致雙重處理 | 檢查模組邏輯 |
AutoEventWireup="false" + 手動掛接 是 WebForms 專案的標準配置,能徹底杜絕 Page_Load 雙重執行,並符合 Microsoft 官方建議。新專案請從專案範本層面固定此設定。