Gotchas (and workarounds) with ASP.NET double submit prevention using jQuery

Double submit prevention is one of those things that developers sometimes have a hard time “getting”. It has an obvious fix – JUST CLICK THE BUTTON ONCE! No matter how obvious that fix is for us developers, chances are that at some point you’re going to be asked to go a little further and add code to prevent people from clicking your submit buttons twice – as was the case for me recently, when I had to look at this issue in  2 separate legacy codebases that we were lucky enough to inherit from other dev teams.

Both were sending mail in the codebehind OnClick event, which can be fine if your mail server is nice and close (but is usually a bad idea), and in both cases doing full refactoring to get the delay of the click event down wasn’t an option due to budget, so I was looking for a quick and effective way to fix the problem.

Both sites were running ASP.NET, and both used jQuery so I thought I’d give this commonly used approach a go:

   1:  $("form").live("submit",(function(e) {  $('button[type=submit]', this).attr('disabled', 'disabled'); }));

Despite this being commonly recommended, it didn’t work at all. After doing a bit of digging and testing of a few things (ASP.NET’s generated form name, multiple different jQuery versions, and a few other obvious debugging things) it became pretty apparent that something wasn’t quite right.

It seems that when you set the CSS attribute of an ASP.NET button to ‘disabled’ in certain browsers (we’re looking at you here IE), then the ASP.NET engine decides that since the button is disabled then its event shouldn’t run. However as you’ve clicked and submitted, it still performs the postback, but without your code executing. So the page refreshes/reloads, but your code doesn’t execute - that’s less than ideal!

So here’s a couple of alternative approaches you can use. All of these are pretty simple, and you’ll probably want to tweak them a little for your environment (especially if you are or aren’t using inbuilt ASP.NET validators):

1. Avoid the issue by using setTimeout

   1:  $(function () {
   2:   
   3:      $('[id$=btnTest]').click(function () {
   4:   
   5:          if (typeof(Page_ClientValidate) == 'function' && Page_ClientValidate() == false) { 
   6:              return false;
   7:          }            
   8:          
   9:          var button = this;
  10:   
  11:          setTimeout(function () {
  12:              $(button).attr('disabled', 'disabled');
  13:          }, 100);
  14:      });
  15:  });

As the title says, this disables the submit button 100ms after it was clicked. In effect this looks instant to the user, but allows the ASP.NET postback to run properly. In this example my button name is btnTest (and it’s being selected via a Wildcard so this will work fine in a master page), however you could also modify this to disable all buttons that match a specific class or disable all buttons using 'button[type=submit]’. The check for Page_ClientValidate is there to add ASP.NET validator support – as we don’t want to disable the button if the page’s content isn’t valid – if you’re not using ASP.NET validators then simply remove lines 5-7.

What if you don’t like using setTimeout? Ok then:

2. Hide the button instead of disabling it

   1:  $(function () {
   2:      $("form").live("submit", (function (e) {
   3:   
   4:          if (typeof(Page_ClientValidate) == 'function' && Page_ClientValidate() == false) { 
   5:              return false;
   6:          }    
   7:   
   8:          $('.submitbutton').hide();
   9:          $('.submitbutton').after('Please Wait, Submitting..');
  10:      }));
  11:  });

ASP.NET doesn’t mind if we hide the button instead of disabling it, and that’s what the code above does. Again with ASP.NET validator support, this time we’re going to hide every button with a class of ‘submitbutton’ and replace it with some text. If you’ve got a lot of buttons on the page then this could look a bit funky, so replace the class with a specific id/wildcard if you need. Also if you prefer, instead of using ‘Please wait’ text, you could insert an AJAX spinner image, or insert a placeholder button which is set to disabled (as this new button wasn’t the one that was clicked, having it disabled isn’t an issue).

Don’t like that approach? Right, I’ve got one more for you:

3. No visual changes, but add a click handler on submit

   1:  $(function () {
   2:      $("form").live("submit", (function (e) {
   3:   
   4:          if (typeof (Page_ClientValidate) == 'function' && Page_ClientValidate() == false) {
   5:              return false;
   6:          }
   7:   
   8:          $('input[type=submit]').click(function () {
   9:              alert('Quit your clicking!');
  10:              return false;
  11:          });
  12:      }));
  13:  });

This example (again with ASP.NET validator support) doesn’t change anything visually – however when the form is being submitted it’ll add click handlers to all the submit input elements that will pop up an alert to the user if they click again, and return false so your code won’t execute a second time. If you use buttons instead of inputs then simply change 'input[type=submit]’ in line 8 to ‘button[type=submit]’, and of course you could change the alert text to something educational for the user or simply remove it altogether.

The above 3 examples are pretty simple, but are effective, and should be easy to adapt to different scenarios. Happy clicking!

Tags: , ,

Posted on Saturday, November 05, 2011 3:11 PM |

Like this? Share it!

  • # re: Gotchas (and workarounds) with ASP.NET double submit prevention using jQuery
    Gravatar
    Commented on 11/15/2011 7:48 PM

    Funny, I just had to do this today. But I ended up using jquery dialog with progress indicator. Seemedto work well.

Post a comment
Please add 8 and 3 and type the answer here:
Remember me?
Ensure the word in this box says 'orange':