Resposta Rápida / TL; DR
Para as pessoas preguiçosas por aí:
Install-Package MagicalUnicornMvcErrorToolkit -Version 1.0
Em seguida, remova esta linha de global.asax
GlobalFilters.Filters.Add(new HandleErrorAttribute());
E isso é apenas para o IIS7 + e o IIS Express.
Se você estiver usando Cassini ... bem ... hum ... er ... estranho ...
Resposta longa e explicada
Eu sei que isso foi respondido. Mas a resposta é MUITO SIMPLES (felicidades a David Fowler e Damian Edwards por realmente responderem a isso).
Não há necessidade de fazer nada personalizado .
Pois ASP.NET MVC3
todos os pedaços estão lá.
Passo 1 -> Atualize seu web.config em DOIS spots.
<system.web>
<customErrors mode="On" defaultRedirect="/ServerError">
<error statusCode="404" redirect="/NotFound" />
</customErrors>
e
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="500" path="/ServerError" responseMode="ExecuteURL" />
</httpErrors>
...
<system.webServer>
...
</system.web>
Agora, observe cuidadosamente as ROTAS que decidi usar. Você pode usar qualquer coisa, mas minhas rotas são
/NotFound
<- para um 404 não encontrado, página de erro.
/ServerError
<- para qualquer outro erro, inclua erros que acontecem no meu código. este é um erro interno do servidor 500
Veja como a primeira seção <system.web>
possui apenas uma entrada personalizada? A statusCode="404"
entrada? Eu listei apenas um código de status porque todos os outros erros, incluindo o 500 Server Error
(ou seja, aqueles erros irritantes que acontecem quando seu código tem um bug e trava a solicitação do usuário) .. todos os outros erros são tratados pela configuração defaultRedirect="/ServerError"
.. que diz , se você não for uma página 404 não encontrada, vá para a rota /ServerError
.
Está bem. que está fora do caminho .. agora para minhas rotas listadas emglobal.asax
Etapa 2 - Criando as rotas no Global.asax
Aqui está a minha seção de rota completa ..
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new {favicon = @"(.*/)?favicon.ico(/.*)?"});
routes.MapRoute(
"Error - 404",
"NotFound",
new { controller = "Error", action = "NotFound" }
);
routes.MapRoute(
"Error - 500",
"ServerError",
new { controller = "Error", action = "ServerError"}
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
}
Que lista duas rotas de ignorar -> axd's
e favicons
(ooo! Bônus ignora rota, para você!) Então (e a ordem é IMPERATIVA AQUI), eu tenho minhas duas rotas explícitas de tratamento de erros .. seguidas por outras rotas. Nesse caso, o padrão. Claro que tenho mais, mas isso é especial para o meu site. Apenas verifique se as rotas de erro estão no topo da lista. A ordem é imperativa .
Finalmente, enquanto estamos dentro do nosso global.asax
arquivo, NÃO registramos globalmente o atributo HandleError. Não, não, não senhor. Nadda. Não. Nien. Negativo. Noooooooooo ...
Remova esta linha de global.asax
GlobalFilters.Filters.Add(new HandleErrorAttribute());
Etapa 3 - Crie o controlador com os métodos de ação
Agora .. adicionamos um controlador com dois métodos de ação ...
public class ErrorController : Controller
{
public ActionResult NotFound()
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View();
}
public ActionResult ServerError()
{
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
// Todo: Pass the exception into the view model, which you can make.
// That's an exercise, dear reader, for -you-.
// In case u want to pass it to the view, if you're admin, etc.
// if (User.IsAdmin) // <-- I just made that up :) U get the idea...
// {
// var exception = Server.GetLastError();
// // etc..
// }
return View();
}
// Shhh .. secret test method .. ooOOooOooOOOooohhhhhhhh
public ActionResult ThrowError()
{
throw new NotImplementedException("Pew ^ Pew");
}
}
Ok, vamos verificar isso. Primeiro de tudo, há NO [HandleError]
atributo aqui. Por quê? Porque a ASP.NET
estrutura interna já está lidando com erros E nós especificamos toda a merda que precisamos fazer para lidar com um erro :) É neste método!
Em seguida, tenho os dois métodos de ação. Nada difícil lá. Se você deseja mostrar qualquer informação de exceção, pode usar Server.GetLastError()
para obter essa informação.
Bônus WTF: Sim, criei um terceiro método de ação para testar o tratamento de erros.
Etapa 4 - Criar as vistas
E, finalmente, crie duas visualizações. Coloque-os no ponto de visualização normal, para este controlador.
Comentários de bônus
- Você não precisa de um
Application_Error(object sender, EventArgs e)
- Todas as etapas acima funcionam 100% perfeitamente com o Elmah . Elmah fraking wroxs!
E isso, meus amigos, deveria ser isso.
Agora, parabéns por ler muito e tenha um unicórnio como prêmio!