Estou usando RC2
Usando o roteamento de URL:
routes.MapRoute(
"Error",
"{*url}",
new { controller = "Errors", action = "NotFound" } // 404s
);
O item acima parece atender a solicitações como esta (assumindo a configuração padrão das tabelas de rotas pelo projeto inicial do MVC): "/ blá / blá / blá / blá"
Substituindo HandleUnknownAction () no próprio controlador:
// 404s - handle here (bad action requested
protected override void HandleUnknownAction(string actionName) {
ViewData["actionName"] = actionName;
View("NotFound").ExecuteResult(this.ControllerContext);
}
No entanto, as estratégias anteriores não tratam uma solicitação para um controlador Ruim / Desconhecido. Por exemplo, eu não tenho um "/ IDoNotExist", se eu solicitar isso, obtenho a página 404 genérica do servidor da web e não o meu 404 se eu usar o roteamento + substituição.
Então, finalmente, minha pergunta é: existe alguma maneira de capturar esse tipo de solicitação usando uma rota ou algo mais na própria estrutura MVC?
Ou devo apenas usar o Web.Config customErrors como meu manipulador 404 e esquecer tudo isso? Presumo que, se eu for com customErrors, terei que armazenar a página 404 genérica fora de / Views devido às restrições da Web.Config no acesso direto.
Respostas:
O código é obtido em http://blogs.microsoft.co.il/blogs/shay/archive/2009/03/06/real-world-error-hadnling-in-asp-net-mvc-rc2.aspx e funciona no asp.net MVC 1.0 também
Veja como eu manejo exceções de http:
fonte
Requisitos para 404
A seguir, são apresentados meus requisitos para uma solução 404 e abaixo mostro como implementá-la:
Solução
Eu acho que você deve economizar
Application_Error
no Global.asax para coisas mais altas, como exceções não tratadas e log (como mostra a resposta de Shay Jacoby ), mas não no tratamento 404. É por isso que minha sugestão mantém o material 404 fora do arquivo Global.asax.Etapa 1: tenha um lugar comum para a lógica de erro 404
Essa é uma boa idéia para manutenção. Use um ErrorController para que futuras melhorias na sua página 404 bem projetada possam se adaptar facilmente. Além disso, verifique se a sua resposta possui o código 404 !
Etapa 2: use uma classe Controller básica para chamar facilmente sua ação 404 personalizada e conectar
HandleUnknownAction
404s no ASP.NET MVC precisam ser capturados em vários locais. O primeiro é
HandleUnknownAction
.O
InvokeHttp404
método cria um local comum para o roteamento para aErrorController
novaHttp404
ação. Pense SECO !Etapa 3: Use a injeção de dependência em sua fábrica de controladores e conecte 404 HttpExceptions
Assim (não precisa ser o StructureMap):
Exemplo MVC1.0:
Exemplo MVC2.0:
Eu acho que é melhor pegar erros mais perto de onde eles se originam. É por isso que eu prefiro o acima ao
Application_Error
manipulador.Este é o segundo lugar para capturar 404s.
Etapa 4: adicione uma rota NotFound ao Global.asax para URLs que não sejam analisados no seu aplicativo
Essa rota deve apontar para a nossa
Http404
ação. Observe que ourl
parâmetro será um URL relativo porque o mecanismo de roteamento está removendo a parte do domínio aqui? É por isso que temos toda essa lógica de URL condicional na Etapa 1.Este é o terceiro e último local para capturar 404s em um aplicativo MVC que você não se invoca. Se você não pegar rotas sem correspondência aqui, o MVC passará o problema para o ASP.NET (Global.asax) e você realmente não deseja isso nessa situação.
Etapa 5: finalmente, chame 404s quando seu aplicativo não encontrar algo
Como quando um ID incorreto é enviado ao meu controlador de empréstimos (deriva de
MyController
):Seria bom se tudo isso pudesse ser conectado em menos locais com menos código, mas acho que essa solução é mais sustentável, mais testável e bastante pragmática.
Obrigado pelo feedback até agora. Eu adoraria ter mais.
NOTA: Isso foi editado significativamente a partir da minha resposta original, mas a finalidade / requisitos são os mesmos - é por isso que não adicionei uma nova resposta
fonte
customErrors
seção web.config define páginas de redirecionamento estático que são tratadas em alto nível no aspnet, se não no IIS. Isso não é o que eu queria, pois precisava que o resultado fosse MVC Views (para que eu possa ter dados neles etc.). Eu não diria categoricamente que "customErrors
é obsoleto no MVC", mas para mim e para essa solução 404 eles certamente são.ObjectFactory.GetInstance
para o MVC3,DependencyResolver.Current.GetService
então é mais genérico. Estou usando o Ninject.O ASP.NET MVC não suporta muito bem as páginas 404 personalizadas. Fábrica de controlador personalizado, rota abrangente, classe de controlador de base com
HandleUnknownAction
- argh!As páginas de erro personalizadas do IIS são a melhor alternativa até agora:
web.config
ErrorController
Projeto de exemplo
fonte
customErrors mode="On"
junto com oHandleErrorAttribute
para ser funcional. Páginas de erro personalizadas para exceções não tratadas em ações do controlador não são mais veiculadas.Resposta Rápida / TL; DR
Para as pessoas preguiçosas por aí:
Em seguida, remova esta linha de
global.asax
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.
e
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 500Veja como a primeira seção
<system.web>
possui apenas uma entrada personalizada? AstatusCode="404"
entrada? Eu listei apenas um código de status porque todos os outros erros, incluindo o500 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çãodefaultRedirect="/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 em
global.asax
Etapa 2 - Criando as rotas no Global.asax
Aqui está a minha seção de rota completa ..
Que lista duas rotas de ignorar ->
axd's
efavicons
(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
Etapa 3 - Crie o controlador com os métodos de ação
Agora .. adicionamos um controlador com dois métodos de ação ...
Ok, vamos verificar isso. Primeiro de tudo, há NO
[HandleError]
atributo aqui. Por quê? Porque aASP.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
Application_Error(object sender, EventArgs e)
E isso, meus amigos, deveria ser isso.
Agora, parabéns por ler muito e tenha um unicórnio como prêmio!
fonte
?aspxerrorpath=/er/not/found
de ter em urls.Eu investiguei MUITO sobre como gerenciar corretamente 404s no MVC (especificamente MVC3) , e isso, IMHO é a melhor solução que eu vim:
Em global.asax:
Controlador de erros:
(Opcional)
Explicação:
AFAIK, existem 6 casos diferentes em que aplicativos do ASP.NET MVC3 podem gerar 404s.
(Gerado automaticamente pelo ASP.NET Framework :)
(1) Um URL não encontra uma correspondência na tabela de rotas.
(Gerado automaticamente pelo ASP.NET MVC Framework :)
(2) Um URL encontra uma correspondência na tabela de rotas, mas especifica um controlador inexistente.
(3) Um URL encontra uma correspondência na tabela de rotas, mas especifica uma ação inexistente.
(Gerado manualmente :)
(4) Uma ação retorna um HttpNotFoundResult usando o método HttpNotFound ().
(5) Uma ação lança uma HttpException com o código de status 404.
(6) Uma ação modifica manualmente a propriedade Response.StatusCode para 404.
Normalmente, você deseja realizar três objetivos:
(1) Mostre uma página de erro 404 personalizada ao usuário.
(2) Mantenha o código de status 404 na resposta do cliente (especialmente importante para SEO).
(3) Envie a resposta diretamente, sem envolver um redirecionamento 302.
Existem várias maneiras de tentar fazer isso:
(1)
Problemas com esta solução:
2)
Problemas com esta solução:
(3)
Problemas com esta solução:
4)
e
Problemas com esta solução:
As pessoas que já enfrentaram problemas antes tentaram criar suas próprias bibliotecas (consulte http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html ). Mas a solução anterior parece cobrir todos os casos sem a complexidade de usar uma biblioteca externa.
fonte
public ActionResult NotFound() {}
no seu ErrorController. Além disso, você pode explicar como_NotFound
seria a sua parcial para solicitações AJAX?MissingMethodException: Cannot create an abstract class
em linhac.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
Alguma idéia?Eu realmente gosto da solução cottsaks e acho que é explicado com muita clareza. minha única adição foi alterar o passo 2 da seguinte maneira
Basicamente, isso impede que URLs que contêm ações inválidas e controladores acionem a rotina de exceção duas vezes. por exemplo, para URLs como asdfsdf / dfgdfgd
fonte
A única maneira de conseguir que o método do @ cottsak funcionasse para controladores inválidos era modificar a solicitação de rota existente no CustomControllerFactory, da seguinte maneira:
Devo mencionar que estou usando o MVC 2.0.
fonte
Aqui está outro método usando as ferramentas MVC, que você pode manipular solicitações para nomes de controladores incorretos, nomes de rotas incorretos e qualquer outro critério que considerar adequado dentro de um método Action. Pessoalmente, prefiro evitar o maior número possível de configurações do web.config, porque elas fazem o redirecionamento 302/200 e não suportam ResponseRewrite (
Server.Transfer
) usando as visualizações do Razor. Prefiro retornar um 404 com uma página de erro personalizada por motivos de SEO.Parte disso é uma nova abordagem da técnica de cottsak acima.
Essa solução também usa configurações mínimas do web.config, favorecendo os filtros de erro do MVC 3.
Uso
Basta lançar um HttpException de uma ação ou ActionFilterAttribute personalizado.
Passo 1
Adicione a seguinte configuração ao seu web.config. Isso é necessário para usar o HandleErrorAttribute do MVC.
Passo 2
Adicione um HandleHttpErrorAttribute personalizado semelhante ao HandleErrorAttribute da estrutura MVC, exceto por erros de HTTP:
etapa 3
Adicione filtros ao GlobalFilterCollection (
GlobalFilters.Filters
) emGlobal.asax
. Este exemplo roteará todos os erros InternalServerError (500) para a visualização compartilhada de erros (Views/Shared/Error.vbhtml
). Os erros NotFound (404) também serão enviados para ErrorHttp404.vbhtml nas visualizações compartilhadas. Adicionei um erro 401 aqui para mostrar como isso pode ser estendido para códigos de erro HTTP adicionais. Observe que essas devem ser visualizações compartilhadas e todas elas usam oSystem.Web.Mvc.HandleErrorInfo
objeto como modelo.Passo 4
Crie uma classe de controlador base e herda dela em seus controladores. Esta etapa nos permite manipular nomes de ações desconhecidos e aumentar o erro HTTP 404 para o nosso HandleHttpErrorAttribute.
Etapa 5
Crie uma substituição ControllerFactory e substitua-a no seu arquivo Global.asax em Application_Start. Esta etapa nos permite gerar a exceção HTTP 404 quando um nome de controlador inválido foi especificado.
Etapa 6
Inclua uma rota especial em sua RoutTable.Routes para a ação BaseController Unknown. Isso nos ajudará a aumentar o 404 no caso em que um usuário acessa um controlador desconhecido ou ação desconhecida.
Sumário
Este exemplo demonstrou como é possível usar a estrutura MVC para retornar 404 códigos de erro HTTP ao navegador sem redirecionar usando atributos de filtro e visualizações de erro compartilhadas. Também demonstra mostrar a mesma página de erro personalizada quando nomes de controladores e ações inválidos são especificados.
Adicionarei uma captura de tela de um nome de controlador inválido, nome da ação e um 404 personalizado gerado a partir da ação Home / TriggerNotFound se eu tiver votos suficientes para postar um =). O violinista retorna uma mensagem 404 quando acesso os seguintes URLs usando esta solução:
post acima da cottsak e esses artigos foram boas referências.
fonte
The IControllerFactory 'aaa.bbb.CustomControllerFactory' did not return a controller for the name '123'.
- alguma idéia de por que eu conseguiria isso?Minha solução abreviada que trabalha com áreas não tratadas, controladores e ações:
Crie uma visualização 404.cshtml.
Crie uma classe base para seus controladores:
Crie uma fábrica de controladores personalizados retornando seu controlador de base como substituto:
Adicione à
Application_Start()
seguinte linha:fonte
No MVC4, o WebAPI 404 pode ser manipulado da seguinte maneira:
CURSOS APICONTROLLER
CONTROLADOR HOME
VISÃO
GLOBAL
RESULTADOS
fonte
Tente NotFoundMVC no nuget. Funciona, sem configuração.
fonte
http://localhost/Views/Shared/NotFound.cshtml
não resulta em uma página 404 personalizada.Minha solução, caso alguém ache útil.
No Web.config:
Em
Controllers/ErrorController.cs
:Adicione um
PageNotFound.cshtml
naShared
pasta e pronto.fonte
model.RequestedUrl = Request.Url.OriginalString.Contains(url) & Request.Url.OriginalString != url ? Request.Url.OriginalString : url;
e nãomodel.RequestedUrl = Request.Url.OriginalString.Contains(url) && Request.Url.OriginalString != url ? Request.Url.OriginalString : url;
(e em vez de &&)?Parece-me que a
CustomErrors
configuração padrão deve funcionar no entanto, devido à confiançaServer.Transfer
que parece que a implementação interna doResponseRewrite
não é compatível com o MVC.Isso me parece uma falha gritante na funcionalidade, então decidi reimplementar esse recurso usando um módulo HTTP. A solução abaixo permite que você lide com qualquer código de status HTTP (incluindo 404) redirecionando para qualquer rota MVC válida, como faria normalmente.
Isso foi testado nas seguintes plataformas;
Benefícios
A solução
Uso
Inclua isso como o módulo HTTP final no seu web.config
Para aqueles que prestam atenção, notarão que, no modo Pipeline integrado, isso sempre responderá com o HTTP 200 devido à maneira como
Server.TransferRequest
funciona. Para retornar o código de erro adequado, eu uso o seguinte controlador de erro.fonte
Lidar com erros no ASP.NET MVC é apenas um problema. Tentei muitas sugestões nesta página e em outras perguntas e sites e nada funciona bem. Uma sugestão foi manipular erros no web.config dentro do system.webserver, mas isso apenas retorna páginas em branco .
Meu objetivo ao criar esta solução era:
Aqui está a minha solução.
1. Adicione o seguinte à seção system.web
O item acima lida com quaisquer URLs não manipulados pelo routes.config e com exceções não tratadas, especialmente aquelas encontradas nas visualizações. Observe que eu usei aspx, não html . É assim que eu posso adicionar um código de resposta no código por trás.
2 . Crie uma pasta chamada Erro (ou o que você preferir) na raiz do seu projeto e adicione os dois webforms. Abaixo está minha página 404;
E no código por trás, defino o código de resposta
Faça o mesmo para a página 500
3 erros punho .Para dentro os controladores. Há muitas maneiras de fazer isso. Isto é o que funcionou para mim. Todos os meus controladores herdam de um controlador base. No controlador base, eu tenho os seguintes métodos
4. Adicione o CustomError.cshtml à sua pasta Views compartilhadas . Abaixo está o meu;
Agora, no seu controlador de aplicativo, você pode fazer algo assim;
Agora, para a ressalva . Ele não manipula erros de arquivo estático. Portanto, se você tiver uma rota como exemplo.com/widgets e o usuário alterá-la para exemplo.com/widgets.html , eles obterão a página de erro padrão do IIS; portanto, você deverá lidar com os erros no nível do IIS de outra maneira.
fonte
Postando uma resposta desde que meu comentário foi muito longo ...
É um comentário e perguntas para a postagem / resposta do unicórnio:
https://stackoverflow.com/a/7499406/687549
Prefiro essa resposta que as outras por sua simplicidade e pelo fato de que aparentemente algumas pessoas da Microsoft foram consultadas. No entanto, tenho três perguntas e, se puderem ser respondidas, chamarei essa resposta de Santo Graal de todas as respostas de erro 404/500 nas interwebs de um aplicativo ASP.NET MVC (x).
@ Pure.Krome
Você pode atualizar sua resposta com o conteúdo de SEO a partir dos comentários apontados pelo GWB (nunca houve menção disso na sua resposta) -
<customErrors mode="On" redirectMode="ResponseRewrite">
e<httpErrors errorMode="Custom" existingResponse="Replace">
?Você pode perguntar aos seus amigos da equipe do ASP.NET se está tudo bem em fazê-lo dessa maneira - seria bom ter alguma confirmação - talvez seja um grande não-não para mudar
redirectMode
eexistingResponse
, dessa maneira, ser capaz de jogar bem com o SEO ?!Você pode adicionar alguns esclarecimentos em torno todas essas coisas (
customErrors redirectMode="ResponseRewrite"
,customErrors redirectMode="ResponseRedirect"
,httpErrors errorMode="Custom" existingResponse="Replace"
, removacustomErrors
completamente, como alguém sugeriu) depois de conversar com seus amigos na Microsoft?Como eu estava dizendo; seria ótimo se pudéssemos tornar sua resposta mais completa, pois essa parece ser uma pergunta bastante popular com mais de 54.000 visualizações.
Atualização : a resposta do unicórnio faz um 302 encontrado e um 200 OK e não pode ser alterado para retornar apenas 404 usando uma rota. Tem que ser um arquivo físico que não seja muito MVC: ish. Então, vamos para outra solução. Que pena, porque essa parecia ser a melhor resposta MVC: ish até agora.
fonte
Adicionando minha solução, que é quase idêntica à de Herman Kan, com uma pequena ruga para permitir que ela funcione no meu projeto.
Crie um controlador de erro personalizado:
Em seguida, crie uma fábrica de controladores personalizados:
Por fim, adicione uma substituição ao controlador de erro personalizado:
E é isso. Não há necessidade de alterações no Web.config.
fonte
1) Faça a classe abstrata Controller.
2) Faça herança dessa classe abstrata em todos os seus controladores
3) E adicione uma exibição chamada "NotFound" na sua pasta View-Shared.
fonte
Passei pela maioria das soluções postadas neste tópico. Embora essa pergunta possa ser antiga, ainda é muito aplicável a novos projetos até agora, por isso passei muito tempo lendo as respostas apresentadas aqui e em outros lugares.
Como o @Marco apontou os diferentes casos em que um 404 pode acontecer, verifiquei a solução que compilei nessa lista. Além de sua lista de requisitos, também adicionei mais um.
Esta solução é 2 vezes:
A primeira parte vem de @Guillaume em https://stackoverflow.com/a/27354140/2310818 . Sua solução cuida de qualquer 404 causado por rota inválida, controlador inválido e ação inválida.
A idéia é criar um formulário da Web e, em seguida, chamar a ação NotFound do seu controlador de erros do MVC. Ele faz tudo isso sem nenhum redirecionamento, para que você não veja um único 302 no Fiddler. O URL original também é preservado, o que torna esta solução fantástica!
A segunda parte vem de @ Germán em https://stackoverflow.com/a/5536676/2310818 . A solução deles cuida de qualquer 404 retornado por suas ações na forma de HttpNotFoundResult () ou lança um novo HttpException ()!
A idéia é fazer um filtro examinar a resposta, bem como a exceção lançada por seus controladores MVC, e chamar a ação apropriada em seu Controlador de Erros. Novamente, esta solução funciona sem nenhum redirecionamento e o URL original é preservado!
Como você pode ver, essas duas soluções juntas oferecem um mecanismo de tratamento de erros muito robusto e atendem a todos os requisitos listados pelo @Marco, bem como aos meus requisitos. Se você quiser ver uma amostra de trabalho ou uma demonstração dessa solução, deixe nos comentários e ficarei feliz em reuni-la.
fonte
Eu já passei por todos os artigos, mas nada funciona para mim: meu requisito, o tipo de usuário, qualquer coisa na sua página 404 personalizada de url deve aparecer.
Achei este artigo muito útil. Deve ser lido de uma só vez. Página de erro de custódia-Ben Foster
fonte