首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 防止按鈕重複提交:核心屬性與完整前後端方案

     編輯:ASP.NET 基礎

最簡單核心做法:兩個屬性搞定

<asp:Button ID="btnSubmit" runat="server" 
    UseSubmitBehavior="false" 
    OnClientClick="this.disabled = true; this.value = '處理中...';"
    Text="送出" OnClick="btnSubmit_Click" />
  • UseSubmitBehavior="false":ASP.NET 不渲染 type="submit",改為 type="button" + __doPostBack,讓我們完全掌控客戶端行為。
  • OnClientClick:點擊瞬間禁用按鈕、改文字,防止連點;PostBack 完成後頁面重整,按鈕自動恢復啟用。

進階需求:後端驗證失敗時保持禁用、成功才恢復

方案 A:RegisterStartupScript 重新啟用 (WebForms 傳統)

protected void btnSubmit_Click(object sender, EventArgs e)
{
    if (!Page.IsValid) return; // 驗證失敗

    // 業務邏輯...
    bool success = DoBusinessLogic();

    if (success)
    {
        // 成功:頁面會重整或導向,按鈕自然恢復
    }
    else
    {
        // 失敗:重新啟用按鈕並提示
        string script = $@"document.getElementById('{btnSubmit.ClientID}').disabled = false; 
                           document.getElementById('{btnSubmit.ClientID}').value = '重新送出';";
        ScriptManager.RegisterStartupScript(this, GetType(), "reEnableBtn", script, true);
    }
}

方案 B:UpdatePanel 部分更新 (AJAX 模式)

<asp:UpdatePanel ID="upMain" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:Button ID="btnSubmit" runat="server" 
            UseSubmitBehavior="false"
            OnClientClick="disableBtn(this);"
            Text="送出" OnClick="btnSubmit_Click" />
        <asp:Label ID="lblMsg" runat="server" />
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="btnSubmit" EventName="Click" />
    </Triggers>
</asp:UpdatePanel>

<script>
function disableBtn(btn) {
    btn.disabled = true;
    btn.value = '處理中...';
}
function enableBtn(btn, text) {
    btn.disabled = false;
    btn.value = text || '送出';
}
</script>
protected void btnSubmit_Click(object sender, EventArgs e)
{
    try
    {
        // 業務邏輯
        bool ok = DoWork();
        lblMsg.Text = ok ? "成功" : "失敗:原因...";
    }
    catch (Exception ex)
    {
        lblMsg.Text = "錯誤:" + ex.Message;
    }
    finally
    {
        // 部分更新完成後,按鈕仍處於 disabled 狀態,需 JS 恢復
        string script = $"enableBtn(document.getElementById('{btnSubmit.ClientID}'), '送出');";
        ScriptManager.RegisterStartupScript(this, GetType(), "reEn", script, true);
    }
}

方案 C:現代前端 (jQuery / Fetch API) 完全分離

<button id="btnSubmit" type="button" class="btn-primary">送出</button>

<script>
$('#btnSubmit').on('click', function () {
    var $btn = $(this).prop('disabled', true).text('處理中...');
    $.post('Handler.ashx', { action: 'submit', data: collectForm() })
        .done(function (res) {
            if (res.success) location.href = res.redirectUrl;
            else alert(res.message);
        })
        .fail(function () { alert('網路錯誤'); })
        .always(function () { $btn.prop('disabled', false).text('送出'); });
});
</script>

比較表

方案 適用場景 優點 缺點
核心屬性法 簡單表單、全頁 PostBack 零 JS 邏輯、無維護成本 驗證失敗時按鈕已恢復,無法保持禁用
RegisterStartupScript 傳統 WebForms、需後端控制 伺服器端決定是否恢復 全頁重整閃爍
UpdatePanel 局部更新、保留 ViewState 無閃爍、程式碼結構熟悉 ViewState 傳輸量大、難除錯
前端 AJAX 現代化、API 分離、SPA 傾向 體驗最佳、前後端分離、可複用 API 需自行處理防偽、驗證、狀態管理

安全性補充:防偽請求 (Anti-Forgery)

<%@ Page ... %>
<asp:HiddenField ID="hfToken" runat="server" />

// Page_Load
if (!IsPostBack) hfToken.Value = Guid.NewGuid().ToString();

// 伺服器端驗證
if (hfToken.Value != Session["FormToken"]?.ToString()) throw new InvalidOperationException("CSRF 攻擊");
// 業務完成後
Session["FormToken"] = Guid.NewGuid().ToString(); // 換新 Token

配合 UseSubmitBehavior="false" 可有效防止重放攻擊與重複提交。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved