我有一个ASP.NET 2.0 Web应用程序,部分使用DropDownList
控件进行导航。当其中一个被更改时,它会导致回发,然后根据在下拉列表中选择的内容将其重定向到另一个URL。
在使用下拉菜单后使用浏览器的“后退”按钮时,我注意到了一些奇怪的行为。程序是这样的:
div
中),进行选择。该页面会重定向到与第一次相同的URL,而不是基于此其他下拉列表重定向到的内容。我已经在Firefox 10和IE9中尝试了这个并且看到了同样的事情。我查看了Firebug中的Net选项卡,并在第3步的POST中看到了正确的控件被引用。但是当我调试它时,错误下拉列表的事件处理程序(步骤1中使用的事件处理程序)将触发。
代码非常简单明了。标记示例:
<asp:DropDownList runat="server" ID="ddlTest" AutoPostBack="true" />
下拉列表实际上不是普通的<asp:DropDownList ... />
元素;我使用类似于this的方法插入optgroup
个元素。
C#示例:
ddlTest.Click += new EventHandler(ddlTest_SelectedIndexChanged);
在ddlTest_SelectedIndexChanged
:
if (ddlTest.SelectedValue != "")
{
Response.Redirect(MyUtilClass.GetUrl(ddlTest.SelectedValue));
}
这里发生了什么?
2012年2月6日更新:我已通过检查Request["__EVENTTARGET"]
事件处理程序中SelectedIndexChanged
的内容来解决此问题。不过,我仍然很好奇它为什么会发生。为什么第一个事件会重复?为什么它只发生在第二个回发发生在第一个回调下面的控件?
答案 0 :(得分:3)
单击后退按钮后,显示上次访问的页面,因为它保存在客户端上不会再次发送回/从服务器请求,这包括最后发布的值,如您选择后显示的一次在点击后退按钮后立即获得第二个DropDownlist。
当您按下第二页上的后退按钮时,第一页的IE上的onload方法(对于其他浏览器参见:http://dean.edwards.name/weblog/2005/09/busted/)会被触发我们可以尝试在重定向页面之前在客户端保存回发操作,我们用JS将其保存在隐藏值上,然后一旦用户返回onload方法评估隐藏是否有值,如果是,那么你改变了页面的位置自身,以便再次请求页面,并清除所有发布的值:
page1.aspx
<script type="text/javascript">
function redir(){
var h=document.getElementById('hdR');
if (h.value=='1'){
h.value='0';
document.location.href='page1.aspx';
}
}
function changeHids(){
var h=document.getElementById('hdR');
h.value='1';
}
</script>
</head>
<body onload="redir();">
<form id="form1" runat="server">
<div>
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" onchange="changeHids();">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem>3</asp:ListItem>
<asp:ListItem>4</asp:ListItem>
</asp:DropDownList>
<br />
<asp:DropDownList ID="DropDownList2" runat="server" AutoPostBack="true" onchange="changeHids();">
<asp:ListItem>5</asp:ListItem>
<asp:ListItem>6</asp:ListItem>
<asp:ListItem>7</asp:ListItem>
<asp:ListItem>8</asp:ListItem>
</asp:DropDownList>
<asp:HiddenField ID="hdR" runat="server"/>
</div>
</form>
</body>
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
Response.Redirect("page2.aspx?ddl=1&val=" & Me.DropDownList1.SelectedValue, True)
End Sub
Protected Sub DropDownList2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList2.SelectedIndexChanged
Response.Redirect("page2.aspx?ddl=2&val=" & Me.DropDownList2.SelectedValue, True)
End Sub
<强> page2.aspx 强>
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Response.Write("ddl:" & Request.QueryString("ddl") & " " & "value:" & Request.QueryString("val"))
End Sub
答案 1 :(得分:3)
Firefox - 添加代码:
protected void Page_Load(object sender, EventArgs e)
{
Response.AppendHeader("Cache-Control", "no-store");
}
Chrome - 添加javascript pageload:
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if (is_chrome) {
document.getElementById("form1").reset();
}
答案 2 :(得分:2)
您可以使用Response.Cache属性来解决此问题,因为您允许将列表缓存在浏览器内存中。来自MSDN SetAllowResponseInBrowserHistory
当HttpCacheability设置为NoCache或ServerAndNoCache时 Expires HTTP标头默认设置为-1;这告诉客户不要 缓存历史记录文件夹中的响应,以便在使用时 后退/前进按钮客户端请求新版本的响应 每一次。您可以通过调用来覆盖此行为 具有allow参数集的SetAllowResponseInBrowserHistory方法 为真。
在页面加载方法中,添加此行。
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetAllowResponseInBrowserHistory(false);
// or else you can do like this
Response.ExpiresAbsolute = DateTime.Now.AddDays(-1d);
Response.Expires = -1;
Response.CacheControl = "No-cache";
}
这样每当你按下时,t每次都会请求一个新版本的响应。
答案 3 :(得分:0)
@Ravi的回答略有不同,对我有用......
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Context.Response.AddHeader("Cache-Control", "max-age=0,no-cache,no-store");
Context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
Context.Response.Cache.SetMaxAge(TimeSpan.Zero);
....
}