防止在asp.net中重复点击按钮

25

我知道这个问题已经被问过了,但是没有一个答案适用于我的项目。

我有一个按钮,当点击它时会调用一个API,因此会有1秒的延迟。

我尝试了几种方法但都没有成功。

btnSave.Attributes.Add("onclick", " this.disabled = true; " + ClientScript.GetPostBackEventReference(btnSave, null) + ";");

即使如此也毫无作用。


你能提一下你尝试过的几件事吗? - Krunal Patil
你问题中的示例对我来说实际上非常有效。看起来像是在禁用后手动调用ASP。谢谢! - crokusek
在 https://dev59.com/D2025IYBdhLWcg3wOzTX#11832053 中有一个有效的答案。 - Stefano Magistri
这个回答解决了你的问题吗?如何防止用户重复点击按钮? - Michael Freidgeim
9个回答

38

防止双击。请在您的aspx页面中添加以下代码。

<script type="text/javascript" language="javascript">

   Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);
   function BeginRequestHandler(sender, args) { var oControl = args.get_postBackElement(); oControl.disabled = true; }

</script>

5
目前为止最佳解决方案 :-) - gchq
2
你能解释一下这是如何工作的吗?它是如何连接到 btnSave 的? - nu everest
2
不起作用。我得到了“错误:'Sys'未定义”...我需要在aspx页面的哪个位置添加此脚本? - Pat
2
@nu everest:必须在客户端(JavaScript)上禁用按钮,因为服务器端禁用不够快。用户可能会在服务器端代码禁用按钮之前点击几次该按钮。(“get_postBackElement”-获取启动异步回发的回发元素。) - Jadran Grba
1
如果您在使用此代码时遇到“错误:未定义'Sys'”的问题,则是因为页面需要一个“ScriptManager”。 - Brian Cryer
显示剩余4条评论

28

这个解决方案简单又有效。在您的按钮中包含以下代码:

OnClientClick="return CheckDouble();"

无论您将JavaScript放在哪里,例如在页面底部:

<script type="text/javascript">
   var submit = 0;
   function CheckDouble() {
     if (++submit > 1) {
     alert('This sometimes takes a few seconds - please be patient.');
     return false;
   }
 }
 </script>

这个很好用,因为它可以通知用户并有助于打破习惯。Windows 在警报对话框弹出时会发出小声的“叮”声。 :) - ahwm
美观、简单易懂...警告信息是个不错的点缀! - Dave
它的运行良好,但服务器验证未触发,例如必填字段验证等。 - Rajesh Pathakoti
我已经添加了这个,它显示了消息,但按钮点击事件仍在服务器端被触发。 - User M
我认为当你的按钮是一个提交按钮时,这种方法不起作用,因为它会导致“submit”变量被重置为零。我可能对此并不正确,但无论如何,这种方法对我来说都没有起作用。 - TizzyFoe

6
大部分上述建议都对我无效。唯一有效的是tezzo提供的方法:
Me.btnSave.Attributes.Add("onclick", "this.disabled=true;")
Me.btnSave.UseSubmitBehavior = False

更简单的方法是,不用在代码后端使用上述内容,而是直接使用以下内容:
   <asp:Button ID="btnSave" runat="server" Text="Save" 
      UseSubmitBehavior="false"
      OnClientClick="this.disabled='true';" 
   </asp:button>

UseSubmitBehavior="false" is the key.


这是最干净的!不过为什么要设置UseSubmitBehavior="false"呢?为什么返回true不能做到postback呢? - Cale
1
第二种方法是最简单的,适用于大多数情况。感谢您的回答! - Razvan

5
您可以使用以下代码来防止双击:

您可以使用以下代码来防止双击:

Me.btnSave.Attributes.Add("onclick", "this.disabled=true;")
Me.btnSave.UseSubmitBehavior = False

你可以使用btnSave_Click来调用你的API。

通常情况下,我在我的Page中有很多Validators:通过设置Validator.SetFocusOnError = True,如果验证失败,我可以运行此代码以重新启用保存按钮。

Me.YourControl.Attributes.Add("onfocus", Me.btnSave.ClientID & ".removeAttribute('disabled');")

它只在第一个之后起作用,我有另一个按钮,上面写着“添加另一个”,在我点击它之后它才能工作,但在第一个上面之前不能工作? - WhiteSpider
好的解决方案。我通过在.aspx页面上添加JavaScript来禁用按钮的点击。我在控件本身上添加了UseSubmitBehavior="false"。这样做对我来说可以达到相同的效果,而不需要依赖于代码后台。 - Jacob Stamm

3

这是我发现的在所有情况下都可行的方案。

<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button1" OnClick="Button1_Clicked" />
<asp:Button ID="Button2" runat="server" Text="Button2" />
</form>

Now here’s the short JavaScript snippet that will disable the button as soon as it is clicked so that when PostBack occurs the button cannot be clicked again.
<script type = "text/javascript">
function DisableButton() {
    document.getElementById("<%=Button1.ClientID %>").disabled = true;
}
window.onbeforeunload = DisableButton;
</script>

The above script disables the ASP.Net Button as soon as the page is ready to do a PostBack or the ASP.Net form is submitted.
But in cases you might want to disable all Buttons and Submit Buttons on the page hence for such cases I have created another function which disables all Buttons and Submit buttons whenever there’s a PostBack or form submission
<script type = "text/javascript">
function DisableButtons() {
    var inputs = document.getElementsByTagName("INPUT");
    for (var i in inputs) {
        if (inputs[i].type == "button" || inputs[i].type == "submit") {
            inputs[i].disabled = true;
        }
    }
}
window.onbeforeunload = DisableButtons;
</script>

0

防止双击。请在您的aspx页面中添加以下代码

<script type = "text/javascript">
function DisableButton() {
document.getElementById("<%=Button1.ClientID %>").disabled = true;
}
window.onbeforeunload = DisableButton;
</script>

3
尽管这可能有所帮助,请不要只是发布代码而没有解释说明我们正在看什么。 - Andrew

0

起初我的解决方案是这样的:

<script>
function disableButton(btn) {
    setTimeout(function () { btn.disabled = true; }, 20);
    return true;
}
</script>
<asp:Button runat="server" ID="btnSave" Text="Save" OnClick="btnSave_Click" OnClientClick="return disableButton(this);" />

如果没有setTimeout,按钮将立即被禁用,然后OnClick事件将不会触发。这种方法的缺点是,如果某些验证失败或出现错误,保存按钮将不再可访问。

因此,我认为禁用按钮不是一个好的解决方案,并想出了另一个解决方案:

     function disableButton(btn) {
        if (btn.hasclicked) return false;
        btn.hasclicked = 1;
        btn.onmouseenter = function () { this.hasclicked = 0; };
        return true;
    }

但是我的同事指出,如果后处理非常缓慢,在完成之前,用户仍然可以通过离开-进入-点击按钮来执行双重提交。因此,我想出了另外两种解决方案:

  1. 在提交表单之前从客户端运行验证。但是,如果您的页面包含多个ValidationGroup,则应该使用传递的ValidationGroup参数多次调用以下Page_ClientValidate():例如 Page_ClientValidate("group1"):

function disableButton(btn) {
  if (Page_ClientValidate) {
    Page_ClientValidate();
    if (!Page_IsValid) {
      btn.setAttribute("btnClicked", "n");
      return true;
    }
  }
  if (btn.getAttribute("btnClicked") == "y") {
    return false;
  } else {
    btn.setAttribute("btnClicked", "y");
    return true;
  }
}

  • 由于ASP.NET页面中只有一个表单(而不是ASP.NET MVC),我们也可以让表单的onsubmit客户端事件拦截双击:

    function disableButton(btn) {
    $("form").submit(function () {
        if (btn.getAttribute("btnClicked") == "y") 
            return false;
        else 
            btn.setAttribute("btnClicked", "y");
            return true;
    });}
    

    我会要求QA测试这两种方法(后编辑:QA已经证明使用此方法非常危险。请参考我的以下评论了解详情)。


  • 我们的QA测试证明第二种方法(最后一种在表单提交点进行检查的方法)不能使用,因为它会使ASP.NET验证机制完全失效。它不仅会绕过客户端的验证机制,还会使您的服务器端验证始终为Page.IsValid == true。使用这种方法是可怕的。永远不要使用它! - wcb1
    如果提交按钮位于UserControl中,则Page_ClientValidate位于DoPostbackWithOptions中,那么选项1也可能会导致问题,具体取决于控件所在的页面以及验证设置的方式以及是否已经调用了Page_ClientValidate。即使您传递了验证组,您最好还是使用服务器端的一次性令牌,以便队列中的后续请求不会使用已使用的令牌。 - Charles Byrne

    0

    这对我也起作用:

    BtnID.Attributes.Add("onclick", "if(typeof (Page_ClientValidate) === 'function' && !Page_ClientValidate()){return false;} this.disabled = true;this.value = '正在处理...';" + ClientScript.GetPostBackEventReference(BtnID, null) + ";");


    1
    请检查答案的格式并添加文本以解释您的代码是如何运作的,并回答问题。 - E. Zacarias

    0

    尝试这种方式,它是一个可行的解决方案:

    对于所有浏览器,包括不支持js的Opera Mobile浏览器,这意味着您的表单在这种类型的浏览器中不会被阻止。

    在Page_load()方法中添加以下内容:

    BtnID.Attributes.Add("onclick", "if(typeof (Page_ClientValidate) === 'function' && !Page_ClientValidate()){return false;} this.disabled = true;this.value = 'Working...';" + ClientScript.GetPostBackEventReference(BtnID, null) + ";");
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接