调用Context.ApplicationInstance.CompleteRequest后,C#ASP.NET事件仍然激活(与Response.Redirect相关)

时间:2017-08-17 10:25:44

标签: c# asp.net redirect exception

尝试遵循Response.Redirect的最佳做法

Response.Redirect(someURl, false);
Context.ApplicationInstance.CompleteRequest();

如本MSDN博客中所述:correct-use-of-system-web-httpresponse-redirect 基本上说:

  

使用不会导致线程中止的CompleteRequest重载   异常。

CompleteRequest的MSDN页面说:

  

使ASP.NET绕过HTTP管道中的所有事件和过滤   执行链并直接执行EndRequest事件。

但是,调用CompleteRequest后的所有页面事件仍然会触发。因此不会跳过任何代码。这似乎与MSDN文档相矛盾。有解决方法吗?我误解了文档吗?

博客文章确实说跳过是在页面级别,但API文档没有说明这一点。我猜测答案只是文档有误导性。

您可以通过调试步进测试非常简单的页面:

<asp:CheckBox ID="CheckBox0" runat="server" OnCheckedChanged="chk_CheckedChanged" />
<asp:CheckBox ID="CheckBox1" runat="server" OnCheckedChanged="chk_CheckedChanged" />
<asp:CheckBox ID="CheckBox2" runat="server" OnCheckedChanged="chk_CheckedChanged" />
<asp:CheckBox ID="CheckBox3" runat="server" OnCheckedChanged="chk_CheckedChanged" />
<asp:Button ID="btnRedirect" runat="server" Text="Click Me" OnClick="btnRedirect_Click" />
<asp:Label ID="lblNotes" runat="server" />

代码:

protected void Page_Load(object sender, EventArgs e)
{
    lblNotes.Text += " Load " + DateTime.Now.ToString();
}

protected void Page_PreRender(object sender, EventArgs e)
{
    lblNotes.Text += " PreRender " + DateTime.Now.ToString();
}

protected void chk_CheckedChanged(object sender, EventArgs e)
{
    Response.Redirect("stackoverflow.com", false);
    Context.ApplicationInstance.CompleteRequest();
}

protected void btnRedirect_Click(object sender, EventArgs e)
{
    lblNotes.Text += " Btn " + DateTime.Now.ToString();
}

如果勾选所有勾选框,则按下按钮会触发许多事件。

1 个答案:

答案 0 :(得分:0)

您似乎认为CompleteRequest()方法将终止类似于Response.Redirect(url, true )的页面执行。但是,正如this article中的John S Reid所解释的那样,CompleteRequest将仅结束ASP.NET应用程序生命周期中页面执行步骤之后发生的应用程序事件,这可能会根据ASP.NET的版本而更改

该页面仍将处理回发事件并呈现页面,但上面的文章中有一个示例,说明如果您对一个示例感兴趣可以防止这种情况。

以下是您的示例的代码:

private m_bIsTerminating = false;

protected void chk_CheckedChanged(object sender, EventArgs e)
{
    Response.Redirect("Default2.aspx", false);
    Context.ApplicationInstance.CompleteRequest();
    m_bIsTerminating = true;
}

protected void btnRedirect_Click(object sender, EventArgs e)
{
    lblNotes.Text = "button click event";
}

protected override void RaisePostBackEvent(IPostBackEventHandler 
    sourceControl, string eventArgument)
{
    if (m_bIsTerminating == false)
    base.RaisePostBackEvent(sourceControl, eventArgument);
}

protected override void Render(HtmlTextWriter writer)
{
    if (m_bIsTerminating == false)
    base.Render(writer);
}

如果您在检查框并单击按钮后进行调试,则复选框将引发回发事件,然后呈现渲染,两者都不会被调用。然后,不会处理按钮单击事件,并且会发生重定向。

另外,我发现这个stackoverflow post与此问题类似,并且有关于CompleteRequest()方法的更多信息。