At first my solution is like this:
<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);" />
Without setTimeout the button will be immediately disabled and then the OnClick event will not be fired. The drawback of this approach is that the Save button will not be accessible anymore if some validation fails or some error happens.
So I don't think disable the button is a good solution, and come up with another solution:
function disableButton(btn) {
if (btn.hasclicked) return false;
btn.hasclicked = 1;
btn.onmouseenter = function () { this.hasclicked = 0; };
return true;
}
But my colleague points out that if the post processing is very slow, before it is finished, the user is still able to perform the double postback by leave-enter-click the button. So I figured out another two solutions:
- Run the validation from client before submitting the form. But if your page contains multiple ValidationGroup, it is said that the following Page_ClientValidate() should be called multiple times with a passed-in ValidationGroup parameter: e.g. 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;
}
}
As the ASP.NET has only one form in a page (not ASP.NET MVC), we can also let the onsubmit client event of the form to intercept the double click:
function disableButton(btn) {
$("form").submit(function () {
if (btn.getAttribute("btnClicked") == "y")
return false;
else
btn.setAttribute("btnClicked", "y");
return true;
});}
I'll ask QA to test those two approaches(Post edit: QA has proved that it is very dangerous to use this approach. Please refer to my following comments for details).