ASP.Net double-click problem ASP.Net double-click problem asp.net asp.net

ASP.Net double-click problem


The general approach is twofold.

Serverside:

  1. On load of the page, generate a token (using System.Random), save it in the session, and write it to a hidden form field
  2. On submit, check that the hidden form field equals the session variable (before setting it again)
  3. Do work

Clientside:

Similar to what you have, but probably just hide the button, and replace it with some text like 'submitting'.

The important thing to note, client side, is that the user may cancel the post by hitting 'escape', so you should consider what to do here (depending on how far along they are the token won't be used, so you'll need to bring the button back from being disabled/hidden).

Complete example follows:

C# (includes code to see it in action):

<html><head runat="server">    <title>double-click test</title>    <script language="c#" runat="server">    private Random        random = new Random();    private static int        TEST = 0;    public void Page_Load (object sender, EventArgs ea)    {        SetToken();    }    private void btnTest_Click (object sender, EventArgs ea)    {        if( IsTokenValid() ){            DoWork();        } else {            // double click            ltlResult.Text = "double click!";        }    }    private bool IsTokenValid ()    {        bool result = double.Parse(hidToken.Value) == ((double) Session["NextToken"]);        SetToken();        return result;    }    private void SetToken ()    {        double next = random.Next();        hidToken.Value       = next + "";        Session["NextToken"] = next;    }    private void DoWork ()    {        TEST++;        ltlResult.Text = "DoWork(): " + TEST + ".";    }    </script></head><body>    <script language="javascript">        var last = null;        function f (obj)        {            obj.src = "http://www.gravatar.com/avatar/4659883ec420f39723c3df6ed99971b9?s=32&d=identicon&r=PG";            // Note: Disabling it here produced strange results. More investigation required.            last = obj;            setTimeout("reset()", 1 * 1000);            return true;        }        function reset ()        {            last.src = "http://www.gravatar.com/avatar/495ce8981a5127a9fd24bd72e7e3664a?s=32&d=identicon&r=PG";            last.disabled = "false";        }    </script>    <form id="form1" runat="server">        <asp:HiddenField runat="server" ID="hidToken" />        <asp:ImageButton runat="server" ID="btnTest"            OnClientClick="return f(this);"            ImageUrl="http://www.gravatar.com/avatar/495ce8981a5127a9fd24bd72e7e3664a?s=32&d=identicon&r=PG" OnClick="btnTest_Click" />        <pre>Result: <asp:Literal runat="server" ID="ltlResult" /></pre>    </form></body></html>


If you have validation on the page, disabling the button client side gets a little tricky. If validation fails, you don't want to disable the button. Here's a snippet that adds the client side event handler:

private void BuildClickOnceButton(WebControl ctl){System.Text.StringBuilder sbValid = new System.Text.StringBuilder();sbValid.Append("if (typeof(Page_ClientValidate) == 'function') { ");sbValid.Append("if (Page_ClientValidate() == false) { return false; }} ");sbValid.Append(ctl.ClientID + ".value = 'Please wait...';");sbValid.Append(ctl.ClientID + ".disabled = true;");// GetPostBackEventReference obtains a reference to a client-side script // function that causes the server to post back to the page.sbValid.Append(ClientScript.GetPostBackEventReference(ctl, ""));sbValid.Append(";");ctl.Attributes.Add("onclick", sbValid.ToString());}

See this asp.net thread for more info.

Update: the above code would be used to add the OnClientClick handler in code behind. You could also write the javascript in your aspx markup like so:

<script type="text/javascript">function disableButton(button){    // if there are client validators on the page    if (typeof(Page_ClientValidate) == 'function')     {        // if validation failed return false        // this will cancel the click event        if (Page_ClientValidate() == false)         {             return false;         }    }    // change the button text (does not apply to an ImageButton)    //button.value = "Please wait ...";    // disable the button    button.disabled = true;    // fire postback    __doPostBack(button.id, '');}</script><asp:ImageButton runat="server" ID="VerifyStepContinue" ImageUrl="button.png"     ToolTip="Go" TabIndex="98" CausesValidation="true" OnClick="methodName"     OnClientClick="return disableButton(this);" />


I have solved this by setting a hidden field on the client click before hitting the server.

Then in the server I check the hidden field and if the value is for example something 'FALSE' that might mean I can or cannot of the action.