One of my West Wind Web Connection customers (but this also applies to ASP.NET) recently posted a question regarding a page that wasn't working correctly when using the Back button. The behavior would be something like this:
- Go to the page
- Click a link that causes a __doPostBack() to occur
- Click the Back button
- Click on a regular Submit button
What happens is that the Submit ends up re-executing the __doPostBack() operation, rather than firing the button click.
It's interesting, because I'd seen this behavior before myself but have never been able to put my finger on what actually causes the behavior and John happened to see the relation.
So, I'm not 100% sure why this happens but after a bit of tracing I do know that what happens is the following:
- __doPostBack event is fired against the server
- Server responds and updates the page appropriately
- Server generates the __EVENTxxxx hidden fields as empty values (correct behavior)
- Back button goes back to the previous page - page is not reloaded from server!
- Browser assigns __EVENTxxx etc. with the previous POST back values
- Button submit bypassess __doPostBack() and so the special vars are posted to the server
- The server detects the __EVENTxxxx form vars and routes events accordingly (incorrect behavior)
When I first saw this I figured this is a bug in my West Wind Web Connection framework code, but I was totally able to duplicate this in ASP.NET where the same behavior occurs.
You can see this behavior with a simple test form:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Postback.aspx.cs" Inherits="Test.Postback"
EnableViewstate="True" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
<link href="Westwind.css" rel="stylesheet" type="text/css">
</head>
<body>
<form id="form1" runat="server">
<a href="Postback.aspx">Reload</a>
<br />
<br />
<asp:TextBox ID="txtName" runat="server"></asp:TextBox>
<asp:Button ID="btnSubmit" runat="server" Text="Button"
onclick="btnSubmit_Click"></asp:Button>
<br />
<asp:CheckBox ID="chkAutoPostback" runat="server" Text="AutoPostBack"
AutoPostback="true" Height="20px" OnCheckedChanged="chkAutoPostback_CheckedChanged" ></asp:CheckBox>
<br />
<br />
<asp:DropDownList runat="server" ID="lstTypes" AutoPostBack="true" OnSelectedIndexChanged="lstTypes_Changed">
<asp:ListItem Text="Red" Value="Red" ></asp:ListItem>
<asp:ListItem Text="Green" Value="Green"></asp:ListItem>
</asp:DropDownList>
</form>
</body>
</html>
and the Codebehind:
namespace Test
{
public partial class Postback : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
Response.Write("button ");
}
protected void chkAutoPostback_CheckedChanged(object sender, EventArgs e)
{
Response.Write("checked ");
}
protected void lstTypes_Changed(object sender, EventArgs e)
{
Response.Write("selectionChanged ");
}
}
}
This code basically spits out which events are fired. If you run this by:
- Loading the page
- Click the checkbox (you see checked event fired)
- Go back (no load - browser cache)
- Click the button
What you'll see is that when you click the button is that both the Checked event and the button submit code are fired. What's interesting is that when you click the BACK button the checkbox stays checked! So now you're firing a change event when in fact nothing has changed.
Apparently this is some sort of browser caching going on with the back button behavior. If I View Source of the generated page, the page has the __Eventxxx values empty. However, if I use a DOM viewer like FireBug it clearly shows that the __EVENTXXXX variables are populated. Here's the view after the Back button operation:
In most situations this is probably not a big issue, but in some situations where you're depending on certain events NOT firing when the shouldn't <s> this may cause issues. For example, in the code above the checked event fires before the button submit so if for whatever reason the value of the checked property adjusts other values before submitting that may effect what the submit behavior is expecting.
Not sure how to address this directly. I wouldn't say this is a bug in ASP.NET, and I'd be even hard pressed to call this a browser bug - browsers do write submitted POST values back into the variables of a page when you click the back button and that certainly has to work.
I suppose the solution is to be very defensive in your coding of change events by explicitly checking for the values of the changes and not just always 'just' executing code on the event. This can be harder than it sounds especially with list controls <s>...
In West Wind Web Connection - well, I have another issue in that unlike ASP.NET it only fires the __EVENTTARGET event and not the button submit at this time. This needs to change so it works as ASP.NET does so at least the submit behavior is fired in this situation. Currently the __doPostback behavior fires the event, but the button submit never fires which results in completely different results.
Tricky one to track down this one - hope this helps someone out in the future.
Other Posts you might also like