UPDATE
Puisque cette réponse fournit une solution, je ne la modifierai pas, mais j'ai trouvé une façon beaucoup plus propre de résoudre ce problème. Voir mon autre réponse pour les détails...
Réponse originale :
J'ai compris pourquoi le Application_Error()
n'est pas invoquée...
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute()); // this line is the culprit
}
...
}
Par défaut (lorsqu'un nouveau projet est généré), une application MVC possède une certaine logique dans la section Global.asax.cs
fichier. Cette logique est utilisée pour le mappage des routes et l'enregistrement des filtres. Par défaut, il n'enregistre qu'un seul filtre : un HandleErrorAttribute
filtre. Lorsque les customErrors sont activés (ou par le biais de requêtes distantes lorsqu'ils sont définis sur RemoteOnly), l'attribut HandleErrorAttribute indique à MVC de rechercher une vue Error et il n'appelle jamais la fonction Application_Error()
méthode. Je n'ai pas pu trouver de documentation à ce sujet mais cela est expliqué dans cette réponse sur programmers.stackexchange.com .
Pour obtenir la méthode ApplicationError() appelée pour chaque exception non gérée, il suffit de supprimer la ligne qui enregistre le filtre HandleErrorAttribute.
Maintenant le problème est : Comment configurer les customErrors pour obtenir ce que vous voulez...
La section customErrors a la valeur par défaut suivante redirectMode="ResponseRedirect"
. Vous pouvez également spécifier que l'attribut defaultRedirect est une route MVC. J'ai créé un ErrorController qui était très simple et j'ai modifié mon web.config pour qu'il ressemble à ceci...
web.config
<customErrors mode="RemoteOnly" redirectMode="ResponseRedirect" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/PageNotFound" />
</customErrors>
Le problème avec cette solution est qu'elle effectue une redirection 302 vers vos URL d'erreur et que ces pages répondent avec un code d'état 200. Cela conduit Google à indexer les pages d'erreur, ce qui est mauvais. Elle n'est pas non plus très conforme aux spécifications HTTP. Ce que je voulais faire, c'était ne pas rediriger et remplacer la réponse originale par mes vues d'erreur personnalisées.
J'ai essayé de changer redirectMode="ResponseRewrite"
. Malheureusement, cette option ne prend pas en charge les routes MVC uniquement des pages HTML statiques ou ASPX. J'ai d'abord essayé d'utiliser une page HTML statique mais le code de réponse était toujours 200 mais, au moins, il n'y avait pas de redirection. J'ai alors eu une idée de cette réponse ...
J'ai décidé d'abandonner le MVC pour la gestion des erreurs. J'ai créé un Error.aspx
et un PageNotFound.aspx
. Ces pages étaient très simples mais elles avaient une pièce magique...
<script type="text/C#" runat="server">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError;
}
</script>
Ce bloc indique à la page d'être servie avec le code d'état correct. Bien sûr, sur la page PageNotFound.aspx, j'ai utilisé HttpStatusCode.NotFound
à la place. J'ai modifié mon web.config pour qu'il ressemble à ceci...
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>
Tout a fonctionné à merveille !
Résumé :
- Retirez la ligne :
filters.Add(new HandleErrorAttribute());
- Utilice
Application_Error()
pour enregistrer les exceptions
- Utiliser customErrors avec un ResponseRewrite, en pointant sur les pages ASPX
- Rendez les pages ASPX responsables de leurs propres codes d'état de réponse.
Il y a quelques inconvénients que j'ai remarqués avec cette solution.
- Les pages ASPX ne pouvant partager aucune balise avec les modèles Razor, j'ai dû réécrire les balises standard d'en-tête et de pied de page de notre site Web pour obtenir un aspect et une convivialité cohérents.
- Les pages *.aspx sont accessibles directement en cliquant sur leur URL.
Il existe des solutions de contournement pour ces problèmes, mais je n'étais pas assez préoccupé par ceux-ci pour faire un travail supplémentaire.
J'espère que cela aidera tout le monde !
0 votes
J'ai exactement le même problème. J'ai également trouvé cette question SO : stackoverflow.com/questions/3713939/ qui suggère de mettre le serveur IIS7 en mode classique. Malheureusement, ce n'est pas une option pour nous. Quelqu'un a-t-il une meilleure solution ?
0 votes
Voici une autre question connexe et ses réponses (dont aucune n'est acceptée) suggèrent de ne pas utiliser du tout Application_Error()... stackoverflow.com/questions/1194578/
0 votes
@Gweebz J'ai posté une réponse sur la façon dont j'ai contourné ce problème, mais je n'ai toujours pas trouvé de documentation solide sur la raison de ce comportement.
1 votes
J'ai ajouté une réponse qui explique pourquoi le
Application_Error()
n'a pas été invoquée. J'ai également expliqué ma solution finale.0 votes
Vraiment recommandé cet article afin de faire fonctionner les erreurs personnalisées.