How will you make it if you never even try?

September 19, 2006

Solving the double-submission problem for ASP.NET websites (Part 1 of 2)

Filed under: ASP.NET — Tags: — charlieflowers @ 1:37 am

A very common problem in applications (both web apps and rich GUI clients) is the “double-submit” problem, or the “multiple-submit” problem. This happens when a user clicks on a button to do some action, and then clicks again before that action is complete. If the action is ordering a product and charging a credit card, for example, the user could be double-billed.

Here’s an overview of how I solved this problem for a web application recently. I hope to post more detail about it soon. (Note: This was for an ASP.NET 1.1 website. Several aspects of the solution would be different for an ASP.NET 2.0 website).

The goal is to prevent users from clicking “submit” (really, any action that causes a postback) more than once, by making the entire contents of the page invisible (and therefore unclickable), and replacing the page contents with a message saying “Please Wait”. To achieve this, I introduced some machinery that hooks into the ASP.NET page rendering process and modifies the rendered HTML such that it contains not only its own contents, but also an invisible div that says “Please wait…” with a little animation. That div is made invisible via the “display: none” CSS setting. To make this machinery convenient to use, it was placed in an abstract base class called “PleaseWaitPage” that inherits from the ASP.NET Page object. The actual content pages that wish to participate in the “please wait” solution then inherit from “PleaseWaitPage”. In addition to injecting the “please wait” div, the PleaseWaitPage class also surrounds the contents of the page itself in a div called “pageContentsDiv”.

Now, when the user submits the form, we simply run some Javascript that sets the “pageContentsDiv” to invisible, and sets the “pleaseWaitDiv” to visible. At this point, it is impossible for the user to click on anything in the contents div.

Of course, nothing is ever quite that easy. There are a whole lot of controls in ASP.NET that can cause postbacks, but which will never execute the Javascript “onsubmit” event of the form. ASP.NET causes these postbacks by calling a client side script function called __doPostback. Anytime that script in a causes a postback, the page is posted back to the server without triggering the form’s “onsubmit” handler.

Therefore, the final obstacle in this approach is to “hijack” the __doPostback function. Say what?

It’s really not as complicated as it sounds (though I don’t have room and time to explain it fully right here). Every function in Javascript is merely a variable that points to a function. For example, if you write the following Javascript function…


function AddThree(x)

{

     return x + 3;

}

… that is actually equivalent to this…


var AddThree = function(x) 

{

   return x + 3;

}

Since it is merely a variable, you can reasign the variable, and you can of course remember the original value of that variable. And that means that you can “hijack” a function, which, in the simplest sense, means that you can say, “Don’t do what this function originally said to do, but instead call my replacement function.” And if you wish, your replacement function can then call the original function after it has done its work (or before, or in the middle of its work).

So, continuing with the AddThree example above, we could do this…


var originalAddThreeFunction = AddThree;

// The next line is REDEFINING the AddThree variable.

AddThree = function(x)

{

   x = x * 2;

   return originalAddThreeFunction(x);

}

Now, if you call AddThree(5), you will no longer get 8. You will get 13, because you have hijacked the function and made it double x before adding 3.

So … back to our original goal. We need to hijack the __doPostback function to make it switch the visibility of the “pleaseWaitDiv” and the “pageContentsDiv”, and then let it proceed with its original task of causing the postback in a way that is consistent with the expectations of ASP.NET.

I haven’t given you enough information to fully acheive this in this post. There are many omitted details — for example, where in the page you should inject the script to hijack __doPostback, and the details of where to hook in to ASP.NET’s rendering of the page. But I have covered the high-level principles here, and I hope to post more in the future. Meanwhile, here are some links I hope you find helpful.

So, hope that helps. Let me know if you have questions, and I hope to follow up with some detail posts soon.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: