Quelles sont les instructions définitives pour la gestion d'erreur personnalisée dans ASP.NET MVC 3?

44

Le processus de gestion personnalisée des erreurs dans ASP.NET MVC (3 dans ce cas) semble être incroyablement négligé. J'ai lu les différentes questions et réponses ici, sur le Web, les pages d'aide pour divers outils (comme Elmah), mais j'ai l'impression d'avoir fait un cercle complet et de ne pas toujours avoir la meilleure solution. Avec votre aide, nous pourrons peut-être définir une nouvelle approche standard pour la gestion des erreurs. Je voudrais garder les choses simples et ne pas trop d'ingénierie.

Voici mes objectifs:

Pour les erreurs / exceptions du serveur:

  1. Afficher les informations de débogage dans dev
  2. Afficher une page d'erreur conviviale en production
  3. Consigner les erreurs et les envoyer par courrier électronique à l'administrateur en production
  4. Renvoyer 500 code de statut HTTP

Pour les erreurs 404 non trouvées:

  1. Afficher une page d'erreur conviviale
  2. Consigner les erreurs et les envoyer par courrier électronique à l'administrateur en production
  3. Renvoyer le code de statut HTTP 404

Existe-t-il un moyen d'atteindre ces objectifs avec ASP.NET MVC?

RyanW
la source
2
J'aimerais que cette question soit migrée RETOUR à SO afin qu'elle puisse obtenir plus de réponses. Je cherche des réponses codées.
Shawn Mclean
@ Shawn Cela ne se produira probablement pas. La question est plus sur le sujet ici que sur SO et il a une réponse acceptée. De plus, les questions ne sont généralement pas remigrées pour des raisons techniques. Si vous avez besoin d’aide pour coder une approche spécifique de gestion des erreurs, veuillez ouvrir une nouvelle question sur StackOverflow. Sinon, les "réponses codées" peuvent constituer un critère trop large pour être utiles ou susceptibles de réponse. Enfin et surtout, le meilleur moyen d'attirer l'attention du modérateur sur une question est de le signaler. Votre commentaire ici serait probablement passé inaperçu s'il ne bloquait pas un drapeau automatique en poussant le compte de commentaires plus de 20.
Adam Lear
Il y avait environ 10 commentaires ici, où sont-ils tous allés?
RyanW
J'ai trouvé une solution qui répond à vos objectifs. Je l'ai comme une autre réponse sur SO: stackoverflow.com/questions/6508415/…
Jesse Webb
1
@AnnaLear Je suis d'accord avec Shawn. J'ai trouvé cette page uniquement via Google. Notez que presque toutes les réponses ci-dessous contiennent des liens BACK to Stack Overflow. Pour moi, cela en dit long, en ce sens qu'il aurait dû être laissé là en premier lieu.
Rebecca

Réponses:

23

Je vais partager la façon dont j'ai fini par le faire, cela faisait partie de la question initiale.

Tout d'abord, les problèmes que j'ai rencontrés:

  1. Si customErrors est activé (c’est-à-dire en production), l’ HandleErrorattribut global avalise les exceptions et affiche votre affichage des erreurs, mais vous ne pouvez pas le connecter avec un outil d’addon comme elmah, car elmah ne le voit jamais. Vous pouvez le consigner à votre avis, je suppose, mais c'est une vue qui semble fausse. L'attribut global HandleError apparaît comme une nouveauté dans le modèle de projet MVC 3 RTM Visual Studio.

  2. customErrors avec les URL pour les points de terminaison MVC renvoie 302 codes d'état. Il existe la propriété redirectmode, mais vous ne pouvez pas faire correspondre les URL mvc dans customErrors et utiliser le mode ResponseRewrite. ( https://stackoverflow.com/questions/781861/customerrors-does-not-work-when-setting-redirectmode-responserewrite/3770265#3770265 )

  3. Éviter complètement les erreurs personnalisées et gérer tout ce qui est personnalisé dans votre application entraîne beaucoup de complexité, IMO. (J'ai adoré ceci: https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095 , mais cela ne convenait pas à notre projet)

Ma solution

J'ai enlevé complètement MVC de l'équation. J'ai supprimé HandleErrorAttributele filtre global dans global.asax et me suis concentré entièrement sur la configuration customErrors, en le décalant de manière à utiliser les redirections WebForm et en le redirigeant vers ResponseRewriteafin d'éviter les codes de réponse HTTP 302.

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

Ensuite, dans l' NotFound.aspxévénement page_load, définissez le Response.StatusCodesur 404 et dans Error.aspx, le code 500.

Résultats:

Les objectifs pour les deux ont été atteints avec les journaux Elmah, la page d'erreur conviviale et le code d'état avec une ligne de code sur le code-behind. Nous ne le faisons pas comme "MVC Way" comme le faisait la solution précédente, mais cela ne me dérange pas s'il s'agit de deux lignes de code.

RyanW
la source
5

Je pense que MVC, ASP et votre infrastructure de gestion de journalisation / exception préférée peuvent très bien gérer vos objectifs. ELMAH et Enterprise Library offrent tous deux une gestion et une journalisation des exceptions facile à utiliser. Choisissez donc votre logiciel favori. Je ne vais pas aborder ici le pour et le contre de chacun.

REMARQUE: vous ne pouvez pas afficher de page d'erreur conviviale ET renvoyer un HTTP 404 ou 500, comme le suggère votre question. Lorsque vous renvoyez une page d'erreur conviviale, le code HTTP renvoyé à votre navigateur est 302. Il s'agit d'une redirection vers la page d'erreur conviviale.

Pages d'erreur conviviales

Il semble que vous puissiez atteindre vos objectifs grâce aux bons paramètres Web.config qui font partie d’ASP.net depuis un certain temps. Vous avez mentionné l'affichage d'informations de débogage lorsque vous êtes dans le développement et l'affichage de pages conviviales en production. Vous pouvez utiliser la section des erreurs personnalisées de web.config pour cela (Définissez CustomErrors = "Off" pour afficher les informations de débogage). Je vais supposer que vous connaissez l'attribut CustomErrors, sinon lisez ceci:

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

Si vous avez besoin d'une plus grande précision du contrôle sur les vues d'erreur que vous affichez, utilisez l'attribut HandleError de MVC. De cette façon, vous pouvez choisir différentes vues d'erreur pour chaque action / contrôleur.

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

Enregistrement des exceptions

Il semble que vous souhaitiez répondre à toutes vos exceptions de la même manière ("Enregistrez les erreurs et envoyez-les par e-mail à l'administrateur en production"). Si tel est le cas, l’option la plus simple est d’ajouter du code à

Application_Error (expéditeur d'objet, EventArgs e)

dans votre global.asax. C’est là que vous pouvez passer au cadre de journalisation choisi.

Si vous souhaitez davantage de contrôle sur la journalisation / la gestion des exceptions, vous pouvez sous-classer HandleErrorAttribute et remplacer

OnException(System.Web.Mvc.ExceptionContext filterContext)

C’est un autre endroit où vous pouvez passer au cadre de journalisation que vous avez choisi.

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

Cela vous donne plus de contrôle que la technique Application_Error mentionnée ci-dessus.

En général, MVC vous offre une grande granularité dans le contrôle de la gestion des erreurs. Si vous n'avez pas besoin de ce contrôle, vous pouvez utiliser les méthodes ASP.net, telles que la définition de pages d'erreur sur votre web.config.

nixon
la source
Merci beaucoup d'avoir ajouté vos pensées. Je pense que le code d'état 302 est un mauvais choix de conception de la part de l'équipe ASP.NET d'origine. Je vais aussi en parler dans mes réponses, il y a quelques options pour le faire. Il semble que certains acteurs du monde MVC abandonnent complètement customErrors et s’occupent de tout dans l’application pour une meilleure capacité de réutilisation et un contrôle accru, comme vous le signalez. Mais j’ai eu peu de succès à les implémenter et j’ai ajouté beaucoup de code qui semblait mieux fonctionner. Plus dans mes réponses ci-dessous.
Je préfère remplacer la méthode OnException pour la journalisation. De cette façon, je sais que je peux tout journaliser, même une erreur survenant à partir d'un appel Ajax qui, selon moi, ne déclenchera pas votre Application_Error.
Alicia
@Alicia échantillon complet de code?
Kiquenet