[c#] Why Response.Redirect causes System.Threading.ThreadAbortException?

When I use Response.Redirect(...) to redirect my form to a new page I get the error:

A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll but was not handled in user code

My understanding of this is that the error is being caused by the webserver aborting the remainder of the page the response.redirect was called on.

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?

This question is related to c# asp.net .net-3.5

The answer is


Here's the official line on the problem (I couldn't find the latest, but I don't think the situation has changed for later versions of .net)


I had that problem too.

Try using Server.Transfer instead of Response.Redirect

Worked for me.


What I do is catch this exception, together with another possible exceptions. Hope this help someone.

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

i even tryed to avoid this, just in case doing the Abort on the thread manually, but i rather leave it with the "CompleteRequest" and move on - my code has return commands after redirects anyway. So this can be done

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();
}

I know I'm late, but I've only ever had this error if my Response.Redirect is in a Try...Catch block.

Never put a Response.Redirect into a Try...Catch block. It's bad practice

As an alternative to putting the Response.Redirect into the Try...Catch block, I'd break up the method/function into two steps.

  1. inside the Try...Catch block performs the requested actions and sets a "result" value to indicate success or failure of the actions.

  2. outside of the Try...Catch block does the redirect (or doesn't) depending on what the "result" value is.

This code is far from perfect and probably should not be copied since I haven't tested it.

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.
    }
}

Also I tried other solution, but some of the code executed after redirect.

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();
    }

So if need to prevent code execution after redirect

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

Response.Redirect() throws an exception to abort the current request.

This KB article describes this behavior (also for the Request.End() and Server.Transfer() methods).

For Response.Redirect() there exists an overload:

Response.Redirect(String url, bool endResponse)

If you pass endResponse=false, then the exception is not thrown (but the runtime will continue processing the current request).

If endResponse=true (or if the other overload is used), the exception is thrown and the current request will immediately be terminated.


This is just how Response.Redirect(url, true) works. It throws the ThreadAbortException to abort the thread. Just ignore that exception. (I presume it is some global error handler/logger where you see it?)

An interesting related discussion Is Response.End() Considered Harmful?.


There is no simple and elegant solution to the Redirect problem in ASP.Net WebForms. You can choose between the Dirty solution and the Tedious solution

Dirty: Response.Redirect(url) sends a redirect to the browser, and then throws a ThreadAbortedException to terminate the current thread. So no code is executed past the Redirect()-call. Downsides: It is bad practice and have performance implications to kill threads like this. Also, ThreadAbortedExceptions will show up in exception logging.

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.

(The documentation to CompleteRequest states that it "Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution". This can easily be misunderstood. It does bypass further HTTP filters and modules, but it doesn't bypass further events in the current page lifecycle.)

The deeper problem is that WebForms lacks a level of abstraction. When you are in a event handler, you are already in the process of building a page to output. Redirecting in an event handler is ugly because you are terminating a partially generated page in order to generate a different page. MVC does not have this problem since the control flow is separate from rendering views, so you can do a clean redirect by simply returning a RedirectAction in the controller, without generating a view.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to asp.net

RegisterStartupScript from code behind not working when Update Panel is used You must add a reference to assembly 'netstandard, Version=2.0.0.0 No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization How to use log4net in Asp.net core 2.0 Visual Studio 2017 error: Unable to start program, An operation is not legal in the current state How to create roles in ASP.NET Core and assign them to users? How to handle Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause() ASP.NET Core Web API Authentication Could not load file or assembly 'CrystalDecisions.ReportAppServer.CommLayer, Version=13.0.2000.0 WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for jquery

Examples related to .net-3.5

Get first element from a dictionary redistributable offline .NET Framework 3.5 installer for Windows 8 How to read an entire file to a string using C#? HTTP Error 500.22 - Internal Server Error (An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode.) Change the Textbox height? How to get current date in 'YYYY-MM-DD' format in ASP.NET? C# Numeric Only TextBox Control Will the IE9 WebBrowser Control Support all of IE9's features, including SVG? Use LINQ to get items in one List<>, that are not in another List<> Get Absolute URL from Relative path (refactored method)