当我使用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?


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


这就是如何响应。重定向(url, true)工作。它抛出ThreadAbortException以中止线程。忽略这个异常。(我假设它是一些全局错误处理程序/记录器,你看到它了吗?)

一个有趣的相关讨论Response.End()是否被认为有害?


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

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

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

Response.Redirect(String url, bool endResponse)

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

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


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

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

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


我也有这个问题。

尝试使用服务器。传输而不是响应。重定向

为我工作。


我知道我迟到了,但我只有在响应时才会出现这种错误。重定向正在尝试中…Catch块。

永远不要放一个响应。重定向到尝试…Catch块。这是不好的做法

作为放置响应的替代方法。重定向到尝试…Catch块,我将把方法/函数分解为两个步骤。

在Try…Catch块执行请求的操作,并设置一个“结果”值来指示操作的成功或失败。 在Try…Catch块是否重定向取决于“结果”值是什么。

这段代码远非完美,可能不应该复制,因为我还没有测试过它。

public void btnLogin_Click(UserLoginViewModel model)
{
    bool ValidLogin = false; // this is our "result value"
    try
    {
        using (Context Db = new Context)
        {
            User User = new User();

            if (String.IsNullOrEmpty(model.EmailAddress))
                ValidLogin = false; // no email address was entered
            else
                User = Db.FirstOrDefault(x => x.EmailAddress == model.EmailAddress);

            if (User != null && User.PasswordHash == Hashing.CreateHash(model.Password))
                ValidLogin = true; // login succeeded
        }
    }
    catch (Exception ex)
    {
        throw ex; // something went wrong so throw an error
    }

    if (ValidLogin)
    {
        GenerateCookie(User);
        Response.Redirect("~/Members/Default.aspx");
    }
    else
    {
        // do something to indicate that the login failed.
    }
}

对于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来做一个干净的重定向,而不生成视图。


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

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

我也尝试了其他解决方案,但一些代码执行后重定向。

public static void ResponseRedirect(HttpResponse iResponse, string iUrl)
    {
        ResponseRedirect(iResponse, iUrl, HttpContext.Current);
    }

    public static void ResponseRedirect(HttpResponse iResponse, string iUrl, HttpContext iContext)
    {
        iResponse.Redirect(iUrl, false);

        iContext.ApplicationInstance.CompleteRequest();

        iResponse.BufferOutput = true;
        iResponse.Flush();
        iResponse.Close();
    }

所以如果需要防止代码执行后重定向

try
{
   //other code
   Response.Redirect("")
  // code not to be executed
}
catch(ThreadAbortException){}//do there id nothing here
catch(Exception ex)
{
  //Logging
}

我甚至试图避免这一点,以防万一在线程上手动做中止,但我宁愿留下它与“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();
}