调用Context.ApplicationInstance.CompleteRequest(Response.Redirect相关)后仍会触发C#ASP.NET事件

调用Context.ApplicationInstance.CompleteRequest(Response.Redirect相关)后仍会触发C#ASP.NET事件,c#,asp.net,redirect,exception,C#,Asp.net,Redirect,Exception,尝试按照最佳实践进行响应。重定向 Response.Redirect(someURl, false); Context.ApplicationInstance.CompleteRequest(); 如本MSDN博客所述: 基本上是说: 使用不会导致线程中止的CompleteRequest重载 例外 的MSDN页面显示: 使ASP.NET绕过HTTP管道中的所有事件和筛选 执行链,并直接执行EndRequest事件 但是,调用CompleteRequest后的所有页面事件仍会触发。因此,不会跳过

尝试按照最佳实践进行响应。重定向

Response.Redirect(someURl, false);
Context.ApplicationInstance.CompleteRequest();
如本MSDN博客所述: 基本上是说:

使用不会导致线程中止的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" />

如果选中所有的勾选框,然后按下按钮,会触发许多事件。

您似乎认为CompleteRequest()方法将终止页面的执行,类似于Response.Redirect(url,true)。但是,正如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);
}
如果要在选中复选框并单击按钮后进行调试,则复选框将引发回发事件,然后引发渲染,这两个事件都不会被调用。然后将不处理按钮单击事件,并发生重定向


此外,我还发现了与此问题类似的问题,并详细介绍了与CompleteRequest()方法有关的一些信息。

在响应中使用false。重定向将结束当前线程的进一步执行。“所以,在某些情况下,它可能会引起问题。”我认为拉维库马尔(Ravikumar)在另一方面说。在Response.Redirect中使用True将结束当前线程的进一步执行,从而引发ThreadAbort异常。这正是我想要避免的。这就是我传递false的原因。您可以共享更多代码或完整的执行线程吗?我不希望它终止执行,我只是希望调用CompleteRequest后不会触发未处理的回发事件,因为MSDN文档暗示会发生这种情况。我的问题是行为与文档不匹配。那篇文章确实提供了一种使用覆盖来引发PostBackEvent和渲染的解决方法。请发布一个答案,包括这部分内容和链接到原来的文章。然后我会将其标记为已接受的答案。“John S Reid”解决方案仅涵盖在页面加载中引发重定向的情况。不幸的是,如果在回发事件中执行重定向,它不会停止所有其他事件的触发。我添加了一个示例,说明如何在checkedchanged事件中重写回发事件/呈现。希望这能让您了解如何在页面加载之外的其他地方进行。另外,这是约翰·S·里德的公司网站,所以这应该是原文。
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);
}