在 ASP.NET Web Forms 開發中,使用者按下 F5 刷新頁面時,瀏覽器會重新發送最後一次的 POST 請求,導致伺服器端按鈕點擊事件被重複執行。典型場景如註冊頁面:使用者填寫資料送出後,若按 F5 刷新,會造成重複註冊資料,產生髒資料與用戶體驗問題。
早期常用「查詢關鍵字是否重複」來阻擋,例如檢查帳號是否已存在。但此法僅適用於有唯一識別欄位的情境,且無法從根本上阻止「重複提交」行為,伺服器仍需處理多餘請求。
核心思路:在客戶端攔截 F5 鍵盤事件(KeyCode = 116),取消預設刷新行為,改為觸發一個隱藏、無實質邏輯的按鈕點擊事件,藉此「消耗」掉重複提交的 Postback。
window.document.onkeydown = KeyStroke;
function KeyStroke() {
var key = event.keyCode;
event.srcElement.releaseCapture();
if (key == 116) { // F5
document.getElementById("Button1").click();
event.keyCode = 0;
event.returnValue = false;
}
}
<asp:Button ID="Button1" runat="server"
Style="position: absolute; left: -9999px; width: 0; height: 0;"
Text="Dummy" OnClick="Button1_Click" />
建議:使用 CSS 將按鈕移出可視區域(left: -9999px),而非 width: 0,避免部分瀏覽器不觸發點擊事件。
protected void Button1_Click(object sender, EventArgs e)
{
// 故意留空,或僅記錄日誌
// Response.Write("偵測到 F5 刷新,已阻擋重複提交");
}
上述做法屬「權宜之計」。業界標準解決方案是 Post-Redirect-Get (PRG) 模式:
302 Redirect 導向結果頁(GET)protected void btnRegister_Click(object sender, EventArgs e)
{
// 處理註冊邏輯...
Response.Redirect("RegisterSuccess.aspx"); // PRG 核心
}
btnSubmit.Attributes["onclick"] = "this.disabled=true; this.value='處理中...'; " + ClientScript.GetPostBackEventReference(btnSubmit, "");攔截 F5 轉向虛擬按鈕可快速止血,但 PRG 模式 + 防重 Token 才是架構層面的正解。建議新專案直接採用 PRG,舊專案若難大幅重構,可先套用 Token 機制降低風險。