ASP.NET AutoPostBack然后返回Back Button很奇怪

时间:2012-10-27 11:49:37

标签: c# asp.net redirect webforms autopostback

为了简单起见,我在ASP.NET表单中有一个下拉列表和一个按钮。下拉列表有一个autopostback函数,调用DropDownList1_SelectedIndexChanged,页面被重定向到某个地方(例如www.google.com),按钮有一个onclick转到Button1_Click1,页面被重定向到www.yahoo.com。

问题:如果我点击按钮,我会去雅虎,这是你所期望的。如果我在浏览器中单击后退按钮并选择下拉列表,我会转到Google,这也是正确的但如果我单击后退按钮然后单击按钮,我将重定向到Google。呃?为什么不去雅虎?

这是我的代码:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="test.aspx.cs" Inherits="test" %>

<!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>Testing Auto-Postback</title>
</head>
<body>
    <form id="form1" runat="server">

                <asp:DropDownList ID="DropDownList1" runat="server" onselectedindexchanged="DropDownList1_SelectedIndexChanged" AutoPostBack="true" ValidationGroup="form1">
                <asp:ListItem>Please select</asp:ListItem>
                <asp:ListItem>Go to Google</asp:ListItem>
                </asp:DropDownList>

                <hr />

                <asp:Button ID="Button1" runat="server" Text="Go to Yahoo" 
                    ValidationGroup="form2" onclick="Button1_Click1" />
    </form>
</body>
</html>

代码背后:

using System;

public partial class test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Response.Redirect("http://www.google.com");
    }

    protected void Button1_Click1(object sender, EventArgs e)
    {
        Response.Redirect("http://www.yahoo.com");
    }
}

如果有人能帮助我,我们将非常感激。

1 个答案:

答案 0 :(得分:1)

好吧,经过一番挖掘后,我发现了以下内容:

当我们点击Button时,页面生命周期直到Button1_Click1事件被引发为止:

Begin PreInit
End PreInit
Begin Init
End Init
Begin InitComplete
End InitComplete
Begin LoadState
End LoadState
Begin ProcessPostData
End ProcessPostData
Begin PreLoad
End PreLoad
Begin Load
End Load
Begin ProcessPostData Second Try
End ProcessPostData Second Try
Begin Raise ChangedEvents
End Raise ChangedEvents
Begin Raise PostBackEvent
Raised Button1_Click1 // Button event here

现在,当我们更改DropDownList时,页面生命周期一直持续到DropDownList1_SelectedIndexChanged事件,如下所示:

Begin PreInit
End PreInit
Begin Init
End Init
Begin InitComplete
End InitComplete
Begin LoadState
End LoadState
Begin ProcessPostData
End ProcessPostData
Begin PreLoad
End PreLoad
Begin Load
End Load
Begin ProcessPostData Second Try
End ProcessPostData Second Try
Begin Raise ChangedEvents
Raised DropDownList1_SelectedIndexChanged // DropDownList event here

对两个页面生命周期进行分析,我们看到在{'ChangedEvents'过程中引发DropDownList1_SelectedIndexChanged事件,此方法比引发Button1_Click1事件的Page'PostBackEvent'过程更早发生。

现在,当您更改DropDownList SelectedIndex时,您将被重定向到Google。当您点击后退按钮时,浏览器会检索该页面的最后一个状态,这意味着DropDownList将保留您之前更改的值。如果在该阶段单击该按钮,则DropDownList和按钮都将在请求值上发送。首先引发DropDownList事件,该网页会再次重定向到Google。

<强>更新

一项工作可以在背后的代码上实现以下内容:

public partial class test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        if (IsPostBack)
        {
            //If the form is posting the button, it means you clicked it
            bool isButtonPostBackEvent = Request.Form.AllKeys.Contains(Button1.UniqueID);

            //Gets the posted value of the DropDownList
            string selectedValue = Request.Form[DropDownList1.UniqueID];

            //Retrieves the index of the DropDownList postedValue
            int valueIndex = DropDownList1.Items.IndexOf(DropDownList1.Items.FindByValue(selectedValue));

            //Verify if posted value of the dropdownlist is different from the server (will raise the SelectedIndexChangedEvent event)
            bool willRaiseSelectedIndexChangedEvent = DropDownList1.SelectedIndex != valueIndex;

            //Verifies if both events will be fired, so apply the button
            //behavior, otherwise let the asp.net do its 
            //magic and raise the events automatically
            if (isButtonPostBackEvent && willRaiseSelectedIndexChangedEvent)
            {
                RedirectToYahoo();
            }
        }
    }

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        RedirectToGoogle();
    }

    protected void Button1_Click1(object sender, EventArgs e)
    {
        RedirectToYahoo();
    }

    private void RedirectToGoogle()
    { 
        Response.Redirect("http://www.google.com");
    }

    private void RedirectToYahoo()
    { 
        Response.Redirect("http://www.yahoo.com");
    }
}

在OnInit事件中,代码标识将由asp.net引发的事件。当两个事件都存在时,我们应用按钮单击行为,因为在这种情况下它具有优先级(它被单击)。

如果你不介意,你也可以更简单:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    if (IsPostBack)
    {
        bool isButtonPostBackEvent = Request.Form.AllKeys.Contains(Button1.UniqueID);

        if (isButtonPostBackEvent)
        {
            RedirectToYahoo();
        }
    }
}