当我使用Response.Redirect(…)将我的表单重定向到一个新页面时,我得到了错误:

类型为'System.Threading '的第一次机会异常。mscorlib.dll中出现ThreadAbortException ` System.Threading类型的异常。在mscorlib.dll中出现ThreadAbortException',但在用户代码中没有处理

我对此的理解是,该错误是由web服务器中止余下的页面响应引起的。重定向被调用。

I know I can add a second parameter to Response.Redirect that is called endResponse. If I set endResponse to True I still get the error but if I set it to False then I do not. I am pretty sure though that that means the webserver is running the rest of the page I redirected away from. Which would seem to be inefficient to say the least. Is there a better way to do this? Something other than Response.Redirect or is there a way to force the old page to stop loading where I will not get a ThreadAbortException?


当前回答

redirect()抛出异常终止当前请求。

这篇KB文章描述了这种行为(也适用于Request.End()和Server.Transfer()方法)。

对于Response.Redirect()存在重载:

Response.Redirect(String url, bool endResponse)

如果传递endResponse=false,则不会抛出异常(但运行时将继续处理当前请求)。

如果endResponse=true(或者使用了其他重载),则抛出异常,当前请求将立即终止。

其他回答

对于ASP中的重定向问题,没有简单而优雅的解决方案。净WebForms。您可以在肮脏的解决方案和乏味的解决方案之间进行选择

Response.Redirect(url)发送一个重定向到浏览器,然后抛出一个ThreadAbortedException来终止当前线程。因此,在Redirect()调用之后不会执行任何代码。缺点:像这样杀死线程是一种糟糕的做法,会影响性能。此外,ThreadAbortedExceptions将显示在异常日志记录中。

Tedious: The recommended way is to call Response.Redirect(url, false) and then Context.ApplicationInstance.CompleteRequest() However, code execution will continue and the rest of the event handlers in the page lifecycle will still be executed. (E.g. if you perform the redirect in Page_Load, not only will the rest of the handler be executed, Page_PreRender and so on will also still be called - the rendered page will just not be sent to the browser. You can avoid the extra processing by e.g. setting a flag on the page, and then let subsequent event handlers check this flag before before doing any processing.

(CompleteRequest的文档声明它“导致ASP。NET可以绕过HTTP管道执行链中的所有事件和过滤”。这很容易被误解。它会绕过进一步的HTTP过滤器和模块,但不会绕过当前页面生命周期中的进一步事件。)

更深层次的问题是WebForms缺乏抽象级别。当您处于事件处理程序中时,您已经处于构建要输出的页面的过程中。在事件处理程序中重定向是丑陋的,因为您要终止部分生成的页面以生成不同的页面。MVC没有这个问题,因为控制流与呈现视图是分开的,所以你可以通过简单地在控制器中返回一个RedirectAction来做一个干净的重定向,而不生成视图。

正确的模式是使用endResponse=false调用重定向重载,并调用IIS管道,一旦你返回控制,它应该直接进入EndRequest阶段:

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

Thomas Marquardt的这篇博客文章提供了更多的细节,包括如何处理Application_Error处理程序内部重定向的特殊情况。

我要做的就是捕捉这个异常,以及其他可能的异常。希望这能帮助到一些人。

 catch (ThreadAbortException ex1)
 {
    writeToLog(ex1.Message);
 }
 catch(Exception ex)
 {
     writeToLog(ex.Message);
 }

下面是关于这个问题的官方说法(我找不到最新的,但我认为。net的后续版本情况没有改变)

我甚至试图避免这一点,以防万一在线程上手动做中止,但我宁愿留下它与“CompleteRequest”和继续-我的代码有返回命令后重定向无论如何。这是可以做到的

public static void Redirect(string VPathRedirect, global::System.Web.UI.Page Sender)
{
    Sender.Response.Redirect(VPathRedirect, false);
    global::System.Web.UI.HttpContext.Current.ApplicationInstance.CompleteRequest();
}