c# - Por que Response.Redirect faz com que System.Threading.ThreadAbortException?




asp.net .net-3.5 (7)

Quando eu uso Response.Redirect (...) para redirecionar meu formulário para uma nova página, recebo o erro:

Uma primeira chance exceção do tipo 'System.Threading.ThreadAbortException' ocorreu em mscorlib.dll
Uma exceção do tipo 'System.Threading.ThreadAbortException' ocorreu em mscorlib.dll, mas não foi tratada no código do usuário

Meu entendimento disso é que o erro está sendo causado pelo servidor da web abortando o restante da página em que o response.redirect foi chamado.

Eu sei que posso adicionar um segundo parâmetro para Response.Redirect que é chamado endResponse. Se eu definir endResponse como True, ainda recebo o erro, mas se eu configurá-lo como False, não recebo o erro. Tenho certeza de que isso significa que o servidor está executando o restante da página da qual eu redirecionei. O que parece ser ineficiente para dizer o mínimo. Existe uma maneira melhor de fazer isso? Algo diferente de Response.Redirect ou existe uma maneira de forçar a página antiga a parar de carregar onde não receberei uma ThreadAbortException ?


É assim que o Response.Redirect (url, true) funciona. Ele lança o ThreadAbortException para anular o segmento. Apenas ignore essa exceção. (Eu presumo que é algum manipulador de erro global / logger onde você o vê?)

Uma interessante discussão relacionada É Response.End () considerado prejudicial?


Aqui está a linha oficial sobre o problema (não consegui encontrar o mais recente, mas não acho que a situação tenha mudado para versões posteriores do .net)


Eu sei que estou atrasado, mas eu só tive esse erro se meu Response.Redirect está em um bloco Try...Catch .

Nunca coloque um Response.Redirect em um bloco Try ... Catch. É má prática

Editar

Em resposta ao comentário do @ Kiquenet, aqui está o que eu faria como uma alternativa para colocar o Response.Redirect no bloco Try ... Catch.

Eu dividiria o método / função em duas etapas.

O primeiro passo dentro do bloco Try ... Catch executa as ações solicitadas e define um valor de "resultado" para indicar o sucesso ou a falha das ações.

O segundo passo fora do bloco Try ... Catch faz o redirecionamento (ou não) dependendo do valor do "resultado".

Este código está longe de ser perfeito e provavelmente não deve ser copiado já que eu não testei

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

Eu também tive esse problema. Tente usar o Server.Transfer em vez de Response.Redirect Trabalhado para mim


O padrão correto é chamar a sobrecarga Redirect com endResponse = false e fazer uma chamada para informar ao pipeline do IIS que deve avançar diretamente para o estágio EndRequest quando você retornar o controle:

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

Esta postagem de blog de Thomas Marquardt fornece detalhes adicionais, incluindo como lidar com o caso especial de redirecionamento dentro de um manipulador Application_Error.


O que eu faço é pegar essa exceção, junto com outras possíveis exceções. Espero que isso ajude alguém.

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

Response.Redirect() lança uma exceção para anular o pedido atual.

Este artigo da KB descreve esse comportamento (também para os métodos Request.End() e Server.Transfer() ).

Para Response.Redirect() existe uma sobrecarga:

Response.Redirect(String url, bool endResponse)

Se você passar endResponse = false , a exceção não será lançada (mas o tempo de execução continuará processando a solicitação atual).

Se endResponse = true (ou se a outra sobrecarga for usada), a exceção será lançada e a solicitação atual será encerrada imediatamente.





.net-3.5