c# - ¿Por qué Response.Redirect causa System.Threading.ThreadAbortException?




asp.net .net-3.5 (7)

Aquí está la línea oficial del problema (no pude encontrar la última, pero no creo que la situación haya cambiado para versiones posteriores de .net)

Cuando uso Response.Redirect (...) para redirigir mi formulario a una nueva página, aparece el error:

Se produjo una primera excepción de oportunidad del tipo 'System.Threading.ThreadAbortException' en mscorlib.dll
Se produjo una excepción de tipo 'System.Threading.ThreadAbortException' en mscorlib.dll pero no se manejó en el código de usuario

Mi entendimiento de esto es que el error está siendo causado por el servidor web que interrumpe el resto de la página en la que se llamó a response.redirect.

Sé que puedo agregar un segundo parámetro a Response.Redirect que se llama endResponse. Si configuro endResponse en True, sigo recibiendo el error, pero si lo establezco en False, no lo hago. Sin embargo, estoy bastante seguro de que eso significa que el servidor web está ejecutando el resto de la página a la que redirigí. Lo que parece ser ineficiente por decir lo menos. ¿Hay una mejor manera de hacer esto? ¿Algo más que Response.Redirect o hay una forma de forzar a la página antigua a que deje de cargar donde no se obtendrá una ThreadAbortException ?


Así es como funciona Response.Redirect (url, true). Lanza la ThreadAbortException para abortar el hilo. Simplemente ignora esa excepción. (Supongo que es un controlador / registrador de errores global donde lo ves?)

Una discusión relacionada interesante ¿Es Response.End () considerado dañino?


Incluso traté de evitar esto, solo en caso de realizar el aborto en el hilo manualmente, pero prefiero dejarlo con la "Solicitud completa" y seguir adelante: mi código tiene comandos de retorno después de redireccionar de todos modos. Así que esto se puede hacer

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

Lo que hago es atrapar esta excepción, junto con otras posibles excepciones. Espero que esto ayude a alguien.

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

Sé que llego tarde, pero solo he tenido este error si mi Response.Redirect está en un bloque Try...Catch .

Nunca coloque un Response.Redirect en un bloque Try ... Catch. Es mala practica

Editar

En respuesta al comentario de @Kiquenet, esto es lo que haría como alternativa a poner el Response.Redirect en el bloque Try ... Catch.

Yo dividiría el método / función en dos pasos.

El primer paso dentro del bloque Try ... Catch realiza las acciones solicitadas y establece un valor de "resultado" para indicar el éxito o el fracaso de las acciones.

Paso dos fuera del bloque Try ... Catch realiza la redirección (o no lo hace) dependiendo de cuál es el valor del "resultado".

Este código está lejos de ser perfecto y probablemente no debería copiarse ya que no lo he probado

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

También probé otra solución, pero parte del código ejecutado después de la redirección.

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

Así que si hay que evitar la ejecución de código después de la redirección

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

Response.Redirect() lanza una excepción para abortar la solicitud actual.

Este artículo de KB describe este comportamiento (también para los métodos Request.End() y Server.Transfer() ).

Para Response.Redirect() existe una sobrecarga:

Response.Redirect(String url, bool endResponse)

Si pasa endResponse = false , la excepción no se produce (pero el tiempo de ejecución continuará procesando la solicitud actual).

Si endResponse = true (o si se usa la otra sobrecarga), se lanza la excepción y la solicitud actual terminará de inmediato.







.net-3.5