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" %>
<meta charset="UTF-8" />
<form id="form1" runat="server">
<asp:ListView ID="lvTest" runat="server" onitemdatabound="lvTest_ItemDataBound">
<asp:Button ID="btnTest" runat="server" OnClick="btnTest_Click" />
<asp:LinkButton ID="lbtnBack" runat="server" Text="Back" Visible="false" OnClick="lbtnBack_Click" />
And the code-behind:
public partial class Default : System.Web.UI.Page
protected void Page_Load(object sender, EventArgs e)
lvTest.DataSource = Enumerable.Range(0, 100);
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
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)
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.
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.