views:

113

answers:

2

Firefox is causing double PostBacks in my asp.net application. IE and Safari do not cause the problem.

I have a form for users to fill out that is inside the second View shown in a MultiView. The MultiView is inside an UpdatePanel so the Views are updated via partial page postbacks. Once they are presented the form they hit submit and their entries are stored in the DB.

In order to prevent users from doubleclicking the submit button I'm using Javascript to disable the button once the form has been submitted. There are several techniques on the web that show how to do this, and I've used this particular solution for quite some time. As I mentioned, only Firefox causes a double PostBack. This seems to be a common problem and if you Google for it you'll find a number of discussions, but I haven’t really found an answer yet. Most of the discussions revolve around the src attribute of an being empty. I am using an ImageButton, but the src attribute should never be empty in my case.

Lets look at the code.

First the markup (abbreviated):

<asp:UpdatePanel ID="UP1" runat="server">
  <ContentTemplate>
    <asp:MultiView id="MV1" runat="server" ActiveViewIndex="0">
      <asp:View id="View1" runat="server">
        Some markup and some asp.net controls
      </asp:View>
      <asp:View id="View2" runat="server">
        <asp:TextBox ID="NameTB" runat="server" />
        <asp:RequiredFieldValidator ID="NameTBRFV" runat="server"
             ControlToValidate="NameTB" ErrorMessage="Required" 
             CssClass="validate" />
        <asp:ImageButton ID="Submit" runat="server"
             ImageUrl="Images/AlumniSubmitButton.jpg" OnClick="Submit_Click" />
      </asp:View>
    </asp:MultiView>
  <ContentTemplate>
</asp:UpdatePanel>

Second the code behind Page Load:

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            Utilities.BindSafeClick(Submit, "Images/AlumniSubmitButton.jpg");
        }
    }

Third the code that adds the onclick which disables the button:

public static void BindSafeClick(Control control, String waitMessage)
{
    StringBuilder sbValid = new StringBuilder();

    Page myPage = control.Page;

    if (control is Button)
    {

        Button myControl = (Button)control;

        sbValid.Append("if (typeof(Page_ClientValidate) == 'function') { ");

        sbValid.Append("if (Page_ClientValidate() == false) { return false; }} ");

        sbValid.Append("this.value = '" + waitMessage + "';");

        sbValid.Append("this.disabled = true;");

        sbValid.Append(myPage.ClientScript.GetPostBackEventReference(myControl, null));

        sbValid.Append(";");

        // the following depends on if submit control has UseSubmitBehavior set.
        // Basically set the opposite here.

        if (myControl.UseSubmitBehavior)
        {
            sbValid.Append("return false;");
        }
        else
        {
            sbValid.Append("return true;");
        }

        myControl.Attributes.Add("onclick", sbValid.ToString());
    }
    else if (control is LinkButton)
    {
        LinkButton myControl = (LinkButton)control;

        sbValid.Append("if (typeof(Page_ClientValidate) == 'function') { ");

        sbValid.Append("if (Page_ClientValidate() == false) { return false; }} ");

        sbValid.Append("this.innerText = '" + waitMessage + "';");

        sbValid.Append("this.disabled = \"disabled\";");

        sbValid.Append(myPage.ClientScript.GetPostBackEventReference(myControl, null));

        sbValid.Append(";");

        myControl.Attributes.Add("onclick", sbValid.ToString());
    }
    else if (control is ImageButton)
    {
        ImageButton myControl = (ImageButton)control;

        sbValid.Append("if (typeof(Page_ClientValidate) == 'function') { ");

        sbValid.Append("if (Page_ClientValidate() == false) { return false; }} ");

        sbValid.Append("this.src = '" + waitMessage + "';");

        sbValid.Append("this.disabled = true;");

        sbValid.Append(myPage.ClientScript.GetPostBackEventReference(myControl, null));

        sbValid.Append(";");

        myControl.Attributes.Add("onclick", sbValid.ToString());
    }
}

I looked at the rendered output when the browser receives the form and noticed that the onclick javascript seems to do two Postbacks.

The same code is rendered in Safari and IE.

Why would Firefox be the only one that does two PostBacks?

Here's the rendered output (added line breaks and spacing to onclick for readability)

<input type="image" name="Submit" id="Submit" src="Images/AlumniSubmitButton.jpg"
 onclick="
          if (typeof(Page_ClientValidate) == 'function') 
           { 
            if (Page_ClientValidate() == false)
             {
              return false; 
             }
           } 
          this.src = 'Images/AlumniSubmitButton.jpg';
          this.disabled = true;
          __doPostBack('Submit','');
          WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Submit&quot;,     &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" style="border-width:0px;" />
A: 

It seems that _doPostBack() and WebForm_DoPostBackWithOptions() both are doing the post back. Both are conflicting each other. For more refer this

Quite interesting..

HotTester
Thanks for your response, HotTester. After reading a link posted in the forum discussion you referred to (http://www.abstraction.net/ViewArticle.aspx?articleID=80), it seems that WebForm_DoPostBackWithOptions() does not cause a PostBack. According to the article, WebForm_DoPostBackWithOptions() will not cause a PostBack even though it is reached since the button is disabled. So it doesn't seem to be anything caused by the added JavaScript and must be something else.
Jeremy Mattingly