Disabling an ASP.NET Button when Clicked

I was answering a question in the ASP.NET forums on Simple-Talk.com about how to avoid the issue of users submitting multiple page requests when they click on buttons.  My first inclination was hey, just disable the button after they click it and everything will be just fine.  So I fired up Visual Studio and threw the following code into a page:

<asp:Button runat="server" Text="My Button" OnClientClick="this.disabled=true;" />

And naturally it failed miserably.  Why?  Because nothing works on the first try — unless fate is trying to store up some catastrophe points to use on you later.  And apparently if you disable a button in the onclick it doesn’t post back for reasons that I haven’t dug into very far.  Not to be outwitted by HTML, Javascript, .NET, or whatever else you can blame for your problems, I tried a myriad of random ideas until I hit upon this — instead of disabling the button when you click it, set the onclick event to fire a function that returns false.  So it looks something like this:

<asp:Button runat="server" Text="My Button" OnClientClick="this.onclick=new Function('return false;');" />

This approach effectively disables the button, but doesn’t gray it out.  So there you go.  If you want a gray button then this isn’t the blog for you, but it does keep people from clicking on it the button more than once.  Naturally, this means that some sticklers out there will whine because the button stays disabled if the request times out or the viewer stops the request manually.  Part of me says leave it disabled as vengeful tribute to the multitudes who quintuple-clicked your button and created a horde of duplicate records for you to delete.  Then there’s the other part of me that likes the JavaScript setTimeout function and a bit of a challenge:

<script type="text/javascript"
    function disableButton(button, resetDelay)
    {
        button.oldonclick = button.onclick;
        button.onclick=noClick; //new Function("return false;";
        setTimeout("enableButton('"+ button.id + "');" resetDelay);                                    
    }
    function noClick()
    {
        alert("Chill - You already submitted this page once. "+
                "Submitting it twice isn't going to make the "+ 
                "server go faster.  Quit hitting the "+
                "freakin' button!";
        return false;
    }
    function enableButton(buttonId)
    {
        var button = document.getElementById(buttonId);
        if(button!=null)
        {
            button.onclick = button.oldonclick;
        }
    }
</script>

The disableButton function copies the “standard” onclick method into a fake property of the button for safe keeping, sets the new onclick to the noClick function (which displays a nice message to the user if they DO try to click), then sets up a delayed function call (read–asynchronous method) that executes after a delay that you set when calling the disableButton method (a value of 1000 for the resetDelay = 1 second, so multiply accordingly for your needs).  Here’s an example of what it looks like in a button:

<asp:Button runat="server" Text="My Button" OnClientClick="disableButton(this,30000)" />

When you click this button, it gets disabled for 30 seconds.  And if a user clicks on that button in the interim, they even get a little feedback on what’s going on.  Just remember, don’t blame me when you get fired for pasting the script into your project and forgetting to change the message.