Curious Event Validation Error in Firefox

   I recently encountered a bug in the ASP.NET Web Forms project I was working on that I found quite interesting. Certain page had a list of items and an item can be selected in a master/detail fashion. All this is done with AJAX via an UpdatePanel. When the page is opened for the first time everything works fine but if the user selects an item and then refreshes the page the next item selection simply does not work. It throws event validation error and all this happens only in Firefox. All other browsers work like a charm.

   Here is the markup for an ASP.NET page to reproduce the bug:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="FxBug.Default"    ViewStateMode="Disabled" %>
<!DOCTYPE html>
<html>
<head runat="server">
   <meta charset="UTF-8" />
   <title></title>
</head>
<body>
   <form id="form1" runat="server">
   <asp:ScriptManager runat="server">
   </asp:ScriptManager>
   <div>
       <asp:UpdatePanel runat="server">
           <ContentTemplate>
               <asp:ListView ID="lvTest" runat="server" onitemdatabound="lvTest_ItemDataBound">
                   <ItemTemplate>
                       <asp:Button ID="btnTest" runat="server" OnClick="btnTest_Click" />
                       <br />
                   </ItemTemplate>
               </asp:ListView>
               <asp:LinkButton ID="lbtnBack" runat="server" Text="Back" Visible="false" OnClick="lbtnBack_Click" />
           </ContentTemplate>
       </asp:UpdatePanel>
   </div>
   </form>
</body>
</html>

And the code-behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace FxBug
{
   public partial class Default : System.Web.UI.Page
   {
       protected void Page_Load(object sender, EventArgs e)
       {
           lvTest.DataSource = Enumerable.Range(0, 100);
           lvTest.DataBind();
       }
       protected void btnTest_Click(object sender, EventArgs e)
       {
           lvTest.Visible = false;
           lbtnBack.Visible = true;
       }
       protected void lbtnBack_Click(object sender, EventArgs e)
       {
           lvTest.Visible = true;
           lbtnBack.Visible = false;
       }
       protected void lvTest_ItemDataBound(object sender, ListViewItemEventArgs e)
       {
           var btnTest = (Button)((ListViewDataItem)e.Item).FindControl("btnTest");
           btnTest.Text = "Button " + e.Item.DataItem.ToString();
       }
   }
}

   Let me repeat the steps to reproduce the bug:
   1. Open the page in Firefox
   2. Click on any button
   3. Refresh the page (F5)
   4. After the page loads click any button
   5. Nothing happens (Event Validation error on the server is swallowed as a JavaScript error)

   I have deployed a page with the code above but keep in mind that at some point it can be removed without notice

   Event validation is a security feature of ASP.NET Web Forms designed to prevent XSRF attacks. I am not going to discuss how it works but the main point is that cryptographically secured string is rendered into a hidden input field. This string is used when the page is post back to the server to validate if the control that caused the POST was rendered when the page was first served. If it is not an exception is thrown.

   All this is really interesting because somehow an action in a previous request causes a POST after a brand new GET to stop working. After all the state of the page is supposed to be reset completely after a new GET.

   After almost a full day of debugging I found out the following in this order:
   1. The correct event validation value is sent from the server to the client.
   2. When the page is updated via the UpdatePanel a new value is sent to the client (which is expected because the controls on the page have changed)
   3. The correct event validation value is sent from the server to the client on the second GET (page refreshed)
   4. No JavaScript changes the event validation value.
   5. Wrong event validation value is sent to the server when a button is pressed. The event validation value is the one that came with the UpdatePanel update.
   6. Firebug shows the broken event validation value while view source shows the correct event validation value.

   As it turns out Firefox decides to autofill form values that have been changed with JavaScript even though the input in question is of type hidden. The same functionality that helps you refill forms you have already submitted wreaks havoc on hidden inputs which are usually used for round tripping state to the server. Other browser vendors seem to know that because all other browsers ignore hidden inputs.

   What is the solution? For normal hidden inputs it is to add autocomplete="off" attribute but the event validation hidden input is not something you can control. One way to work around the issue is to add the attribute to the form itself but this will turn autofill off for every input in that form even where it is useful. I have submitted a bug on Connect about the issue. I expect Microsoft to fix this even though in my opinion this is a bug in Firefox but I doubt they will want to fix a bug that can break existing pages. Even if they do I do not want to get involved with them in any way.
Tags:   english programming 
Posted by:   Stilgar
03:05 12.03.2012

Comments:

First Previous 1 Next Last 

Posted by   Guest (Unregistered)   on   04:29 12.03.2012

He who can destroy a thing, can control a thing. Firefox has proven this, the web would not been constricted by its tight boundries, had it not been for the vast amount of requirments so many browser face us with.

First Previous 1 Next Last 


Post as:



Post a comment: