Двойной постбэк от Firefox в приложении asp.net - PullRequest
0 голосов
/ 22 сентября 2010

Firefox вызывает двойные PostBacks в моем приложении asp.net. IE и Safari не вызывают проблемы.

У меня есть форма для заполнения пользователями, которая находится во втором представлении, показанном в MultiView. MultiView находится внутри UpdatePanel, поэтому представления обновляются с помощью частичной обратной передачи страницы. Как только они представлены, они отправляют форму, и их записи сохраняются в БД.

Чтобы пользователи не могли дважды щелкнуть кнопку отправки, я использую Javascript для отключения кнопки после отправки формы. В Интернете есть несколько методов, которые показывают, как это сделать, и я использовал это конкретное решение довольно давно. Как я уже говорил, только Firefox вызывает двойной PostBack. Похоже, что это общая проблема, и если вы воспользуетесь Google, вы найдете ряд обсуждений, но я так и не нашел ответа. Большинство дискуссий вращаются вокруг атрибута src пустого существа. Я использую ImageButton, но атрибут src никогда не должен быть пустым в моем случае.

Давайте посмотрим на код.

Первая разметка (сокращенно):

<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>

Второй код загрузки страницы:

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

В-третьих, код, который добавляет клик, который отключает кнопку:

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());
    }
}

Я посмотрел на отрендеренный вывод, когда браузер получил форму, и заметил, что javascript onclick, похоже, выполняет две обратной передачи.

Один и тот же код отображается в Safari и IE.

Почему Firefox будет единственным, кто делает два PostBacks?

Вот визуализированный вывод (добавлены разрывы строк и интервалы в onclick для удобства чтения)

<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;" />

Ответы [ 6 ]

3 голосов
/ 28 июля 2011

Это просто, потому что путь к изображению неверен.Когда FireFox не может найти изображение, оно снова выполнит обратную передачу.Мне потребовалось время, чтобы понять это.

2 голосов
/ 16 апреля 2012

Firefox требует return false; в конце оператора JavaScript.Добавление return false; в конце оператора JavaScript будет правильно интерпретироваться другими браузерами.

Поэтому вместо написания этого;

yourButtonControl.Attributes.Add("onclick", "if (Page_ClientValidate('nameOfValidationGroup') == false) { return false; } " + ``Page.ClientScript.GetPostBackEventReference(yourButtonControl, String.Empty) + ";this.disabled = true;");

... напишите это;

yourButtonControl.Attributes.Add("onclick", "if (Page_ClientValidate('nameOfValidationGroup') == false) { return false; } " + Page.ClientScript.GetPostBackEventReference(yourButtonControl, String.Empty) + ";this.disabled = true; return false;");

Мне потребовалось несколько дней проб и ошибок, а также много испытаний, чтобы определить, почему логика моего уровня данных внезапноначал выдавать следующую ошибку:

Transaction (Process ID "...") was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

... только чтобы выяснить, что виновником был Firefox.

В конце концов, это ошибки типате, которые улучшают ваши знания и навыки.; -]

Надеюсь, это поможет многим другим разработчикам.

JavaScript не является злом.Это не так дружелюбно, как управляемый код.

Патрик

1 голос
/ 19 октября 2011

Один из обходных путей - поместить кнопку в DataGridView.Это предотвратит двойную обратную передачу с FireFox.

Создайте DataGridView:

       <asp:GridView ID="GridViewButton" ShowHeader="false" runat="server" AutoGenerateColumns="false" 
                  GridLines="None" OnRowCommand="GridViewButton_RowCommand" CellPadding="0" OnDataBound="GridViewButton_DataBound">
            <Columns>
                <asp:ButtonField Text="Save" CommandName="Save" ButtonType="Button">
                </asp:ButtonField>
            </Columns>
       </asp:GridView>

При PageLoad заполните DataGridView фиктивными данными, чтобы кнопка отображалась:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim dt As New DataTable
    dt.Columns.Add(New DataColumn("col1"))
    Dim dr As DataRow = dt.NewRow
    dt.Rows.Add(dr)
    Me.GridViewButton.DataSource = dt
    Me.GridViewButton.DataBind()
End Sub

В DataBound установите JavaScript, чтобы отключить нажатие кнопки:

Protected Sub GridViewButton_DataBound(ByVal sender As Object, ByVal e As System.EventArgs)

    CType(Me.GridViewButton.Rows(0).Cells(0).Controls.Item(0), Button).Attributes.Add("onclick", "this.disabled=true;")

End Sub

Обработка события щелчка:

Protected Sub GridViewButton_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs)

    If e.CommandName = "Save" Then

         //Do something here

    End If

End Sub
1 голос
/ 29 июля 2011

Время назад у меня возникла та же проблема с ImageButton, и проблема исчезла, когда я установил для атрибута ImageButton AlternateText непустую строку.

1 голос
/ 05 ноября 2010

Попробуйте добавить триггер обратной передачи на кнопку. Секция триггера над закрывающим тегом UpdatePanel.

Пример кода:

<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>
  <Triggers>
    <asp:PostBackTrigger ControlID="Submit" />
  </Triggers>      
</asp:UpdatePanel>
0 голосов
/ 22 сентября 2010

Кажется, что _doPostBack () и WebForm_DoPostBackWithOptions () оба возвращают сообщение. Оба противоречат друг другу. Для более подробной информации это

Довольно интересно ..

...