在 ASP.NET WebForms 中,直接在按鈕 OnClientClick 撰寫 history.go(-1) 或註冊 history.go(-1) 指令碼,點擊後**無法返回預期的上一頁**,甚至停留在當前頁。
ASP.NET 按鈕預設觸發 **PostBack**,頁面會先送出表單至伺服器,伺服器處理完畢再回傳新的 HTML。此時瀏覽器歷史記錄已新增一筆(PostBack 後的頁面),導致「上一頁」實際指向「PostBack 前的同一頁」,而非使用者認知的「上一個瀏覽頁面」。
在伺服器端按鈕事件中註冊啟動指令碼,跳過 PostBack 產生的歷史記錄:
protected void ButtonGoBack_Click(object sender, EventArgs e)
{
// 關鍵:-2 跳過 PostBack 產生的中間頁
string script = "<script>history.go(-2);</script>";
ClientScript.RegisterStartupScript(this.GetType(), "GoBack", script);
}
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
history.go(-2) | 程式碼極少、無需變更架構 | 若中間頁數量不固定(如多次 PostBack、Redirect)會失效 | 單純表單送出、確定只有一層 PostBack |
Request.UrlReferrer 導向 | 精確返回來源頁 | Referrer 可能為空(HTTPS→HTTP、隱私模式、防火牆過濾) | 需可靠返回、可接受偶爾失效 |
| ViewState/Session 記錄 ReturnUrl | 完全可控、支援多層導航 | 需在每個入口頁寫入 ReturnUrl、增加複雜度 | 複雜多步驟流程(精靈、結帳) |
| HyperLink / 一般 <a> 標籤 | 無 PostBack、瀏覽器原生返回行為 | 無法在伺服器端執行邏輯後再返回 | 純導航、無後端處理需求 |
<a href="..."> 或 HyperLink)實現「返回」,避免 PostBack。Response.Redirect(returnUrl),最穩健。history.go(-2) 作為快速修正。
// 頁面 A 連結至頁面 B
<a href="PageB.aspx?ReturnUrl=<%=Server.UrlEncode(Request.Url.AbsoluteUri)%>">前往編輯</a>
// 頁面 B 儲存按鈕
protected void BtnSave_Click(object sender, EventArgs e)
{
// 執行儲存邏輯...
string returnUrl = Request.QueryString["ReturnUrl"];
if (!string.IsNullOrEmpty(returnUrl))
Response.Redirect(returnUrl);
else
Response.Redirect("PageA.aspx"); // fallback
}
ASP.NET PostBack 機制會汙染瀏覽器歷史堆疊,history.go(-2) 只是權宜之計。建立「來源頁傳遞 ReturnUrl → 目標頁處理完畢 Redirect 回 ReturnUrl」的習慣,才是解決導航問題的正統之道。