How do I prevent users clicking a button twice?

I have an old ASP.NET web forms application (.NET 2.0) that has a process that takes 30 seconds or so to run when a button is clicked. I need to prevent the button from being clicked twice. This will prevent posting twice, which causes duplicate data in a database.

I tried adding;

OnClientClick="this.disabled='true';"

to try to disable the button in JavaScript. However, though the button becomes disabled, the postback for the button then doesn't work.

Disabling the button to prevent multiple submissions is the ideal for this application. How can I do this?

EDIT

I am unable to use third-party controls.


If you simply disable the button then ASP.NET won't post the form. Also you want to deal with client-side validation. Here's my solution:

<asp:Button runat="server" ID="btnSave" 
   Text="Save" OnClick="btnSave_Click" 
   OnClientClick="if (!Page_ClientValidate()){ return false; } this.disabled = true; this.value = 'Saving...';" 
   UseSubmitBehavior="false" />

See @Dave Ward's post for a description of UseSubmitBehavior.

If you have multiple validation groups you'll need to enhance this solution for that.


You must return true after the OnClientClick:

OnClientClick="this.disabled='true';return true;"

Any clicks in client-side must return true if the postback is to continue, it's a means of providing client-side validatin on button presses.


You need to also set the Button's UseSubmitBehavior property to false.

Web browsers do not include disabled elements in a form's POST data, even if the element happens to be the button that triggered the form submission in the first place. Unfortunately, ASP.NET WebForms' single-form-page design relies on that bit of information to know which control raised the PostBack and which event handler to execute (i.e. Button1.On_Click).

Switching to UseSubmitBehavior="false" injects a __doPostBack('Button1', '') in the client-side onclick handler to work around that problem. Then, even if you disable the Button, the __doPostBack parameter lets ASP.NET know which control raised the PostBack and which events to fire on the server-side.


Most of this solutions provided above that suggest disabling won't work because you won't get a PostBack. This is the simplest and cleanest working solution I've seen:

OnClientClick="if(this.value === 'Saving...') { return false; } else { this.value = 'Saving...'; }"