Quais são as diretrizes definitivas para tratamento de erros personalizado no ASP.NET MVC 3?

44

O processo de manipulação de erros personalizados no ASP.NET MVC (3 neste caso) parece incrivelmente negligenciado. Eu li as várias perguntas e respostas aqui, na Web, páginas de ajuda de várias ferramentas (como Elmah), mas sinto que segui um círculo completo e ainda não tenho a melhor solução. Com sua ajuda, talvez possamos definir uma nova abordagem padrão para o tratamento de erros. Eu gostaria de manter as coisas simples e não projetar demais isso.

Aqui estão meus objetivos:

Para erros / exceções do servidor:

  1. Exibir informações de depuração no dev
  2. Exibir página de erro amigável na produção
  3. Registre erros e envie-os por e-mail ao administrador em produção
  4. Código de status HTTP de retorno 500

Para erros 404 não encontrados:

  1. Exibir página de erro amigável
  2. Registre erros e envie-os por e-mail ao administrador em produção
  3. Código de status HTTP 404 de retorno

Existe uma maneira de atingir esses objetivos com o ASP.NET MVC?

RyanW
fonte
2
Gostaria que essa pergunta fosse migrada de volta para SO para que ele possa obter mais respostas. Estou procurando respostas codificadas.
Shawn Mclean
@ Shawn É improvável que isso aconteça. A questão está mais no tópico aqui do que no SO e tem uma resposta aceita. As perguntas também geralmente não são migradas novamente por razões técnicas. Se você precisar de ajuda para codificar uma abordagem específica de tratamento de erros, abra uma nova pergunta no StackOverflow. Caso contrário, "respostas codificadas" podem ser critérios muito amplos para serem úteis ou responsáveis. Por último, mas não menos importante, a melhor maneira de atrair a atenção do moderador de uma pergunta é sinalizá-la. Seu comentário aqui provavelmente passaria despercebido se não disparasse uma sinalização automática, pressionando a contagem de comentários acima de 20.
Adam Lear
Costumava haver cerca de 10 comentários aqui, para onde todos eles foram?
RyanW
Encontrei uma solução que atende aos seus objetivos. Eu tê-lo como uma outra resposta em SO: stackoverflow.com/questions/6508415/...
Jesse Webb
1
@AnnaLear Concordo com Shawn. Encontrei esta página apenas pelo Google. Observe que quase todas as respostas abaixo contêm links VOLTAR ao estouro de pilha. Para mim, que fala volumes, porque deveria ter sido deixado lá em primeiro lugar.
Rebecca

Respostas:

23

Vou compartilhar a maneira como acabei fazendo isso, que fazia parte da pergunta original.

Primeiro, os problemas que encontrei:

  1. Com customErrors ativado (ou seja, em produção), o HandleErroratributo global engole exceções e renderiza sua exibição de erro, mas não é possível registrá-lo com uma ferramenta adicional como elmah, pois elmah nunca a vê. Você poderia registrá-lo em sua opinião, suponho, mas é uma visão que parece errada. O atributo global HandleError aparece novo no modelo de projeto do MVC 3 RTM Visual Studio.

  2. customErrors com URLs para pontos de extremidade MVC retorna 302 códigos de status. Existe a propriedade redirectmode, mas você não pode corresponder a URLs do mvc em customErrors e usar o modo ResponseRewrite. ( https://stackoverflow.com/questions/781861/customerrors-does-not-work-when-setting-redirectmode-responserewrite/3770265#3770265 )

  3. Evitar completamente os customErrors e manipular tudo o que é personalizado no seu aplicativo leva a muita complexidade, IMO. (Adorei isso: https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095 , mas não era adequado para o nosso projeto)

Minha solução

Tirei MVC da equação completamente. Eu removi HandleErrorAttributeo filtro global em global.asax e concentrei-me inteiramente na configuração customErrors, deslocando-o para usar os redirecionamentos de WebForm e alterar para o modo de redirecionamento ResponseRewritepara evitar os 302 códigos de resposta HTTP.

<customErrors mode="On" defaultRedirect="/Error.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="/NotFound.aspx" />
</customErrors>

Em seguida, no NotFound.aspxevento page_load, defina Response.StatusCodecomo 404 e em Error.aspx, defina o código 500.

Resultados:

Os objetivos de ambos foram alcançados com os logs do Elmah, a página de erro amigável e o código de status com uma linha de código no code-behind. Não estamos fazendo o "MVC Way" como a solução anterior faz, mas estou bem com isso se forem duas linhas de código.

RyanW
fonte
5

Eu acho que o MVC, ASP e sua estrutura favorita de registro / tratamento de exceções podem lidar com seus objetivos muito bem. O ELMAH e a Enterprise Library fornecem fácil manuseio e registro de exceções, então escolha o seu favorito. Não vou falar dos prós e contras de cada um aqui.

NOTA: você não pode exibir uma página de erro amigável E retornar um HTTP 404 ou 500 como sugere sua pergunta. Quando você retorna uma página de erro amigável, o código HTTP retornado ao seu navegador será 302. Este é um redirecionamento para a página de erro amigável.

Páginas de erro amigáveis

Parece que você pode atingir seus objetivos com as boas configurações do web.config que fazem parte do ASP.net há algum tempo. Você menciona a exibição de informações de depuração no desenvolvimento e a exibição de páginas amigáveis ​​na produção. Você pode usar a seção de erros personalizados do web.config para isso (defina CustomErrors = "Off" para mostrar informações de depuração). Vou assumir que você está familiarizado com o atributo CustomErrors, se não ler isso:

http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx

Se você precisar de maior granularidade de controle sobre quais exibições de erro são exibidas, use o Atributo HandleError do MVC. Dessa forma, você pode escolher diferentes visualizações de erro para cada Ação / Controlador.

http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx

Log de exceção

Parece que você deseja responder a todas as suas exceções da mesma maneira ('Registre erros e envie-os por e-mail ao administrador em produção'). Se for esse o caso, sua opção mais simples é adicionar código ao

Application_Error (remetente do objeto, EventArgs e)

no seu global.asax. É aqui que você pode passar para a estrutura de log escolhida.

Se você deseja ter mais controle sobre o registro / tratamento de exceções, pode subclassificar HandleErrorAttribute e substituir

OnException(System.Web.Mvc.ExceptionContext filterContext)

esse é outro lugar onde você pode passar para a estrutura de log escolhida.

https://stackoverflow.com/questions/183316/asp-net-mvc-handleerror

Isso lhe dá mais controle do que a técnica Application_Error mencionada acima.

Em geral, o MVC oferece uma grande granularidade de controle sobre como lidar com erros. Se você não precisar desse controle, poderá recorrer às maneiras de executar o ASP.net, como definir páginas de erro no seu web.config.

nixon
fonte
Muito obrigado por adicionar seus pensamentos. Eu acho que o código de status 302 é uma má escolha de design pela equipe original do ASP.NET. Vou abordar isso nas minhas respostas também, existem algumas opções para fazer isso. Parece que alguns no mundo MVC estão abandonando completamente os customErrors e lidando com tudo isso no aplicativo para melhor reutilização e mais controle, como você indica. Mas, eu tive sucesso limitado na implementação deles e estava adicionando muito código que parecia melhor. Mais nas minhas respostas abaixo.
Eu prefiro substituir o método OnException para log, desta forma eu sei que posso registrar tudo, mesmo ocorrendo um erro de uma chamada Ajax que eu acho que não acionará seu Application_Error.
Alicia
@Alicia código de exemplo completo?
Kiquenet