MISE À JOUR
Puisque cette réponse fournit une solution, je ne la modifierai pas, mais j'ai trouvé un moyen beaucoup plus propre de résoudre ce problème. Voir mon autre réponse pour plus de détails ...
Réponse originale:
J'ai compris pourquoi la Application_Error()
méthode 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 a une certaine logique dans le Global.asax.cs
fichier. Cette logique est utilisée pour mapper les routes et enregistrer les filtres. Par défaut, il n'enregistre qu'un seul filtre: un HandleErrorAttribute
filtre. Lorsque customErrors est activé (ou via des requêtes distantes lorsqu'il est défini sur RemoteOnly), HandleErrorAttribute indique à MVC de rechercher une vue d'erreur et n'appelle jamais la Application_Error()
méthode. Je n'ai pas pu trouver de documentation à ce sujet, mais elle est expliquée dans cette réponse sur programmers.stackexchange.com .
Pour obtenir la méthode ApplicationError () appelée pour chaque exception non gérée, supprimez simplement 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 est définie par défaut sur redirectMode="ResponseRedirect"
. Vous pouvez également spécifier l'attribut defaultRedirect comme une route MVC. J'ai créé un ErrorController qui était très simple et j'ai changé 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, puis ces pages répondent avec un code d'état 200. Cela conduit Google à indexer les pages d'erreur, ce qui est mauvais. Il n'est pas non plus très conforme à la spécification HTTP. Ce que je voulais faire, ce n'était pas de rediriger et de remplacer la réponse d'origine 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 les pages HTML statiques ou ASPX. J'ai essayé d'utiliser une page HTML statique au début, mais le code de réponse était toujours de 200, mais au moins il n'a pas redirigé. J'ai alors eu une idée de cette réponse ...
J'ai décidé d'abandonner 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 un morceau de magie ...
<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 à être servie avec le code d'état correct. De grossier, sur la page PageNotFound.aspx, j'ai utilisé à la HttpStatusCode.NotFound
place. J'ai changé 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 parfaitement fonctionné!
Résumé:
- Supprimez la ligne:
filters.Add(new HandleErrorAttribute());
- Utiliser la
Application_Error()
méthode pour consigner les exceptions
- Utiliser customErrors avec un ResponseRewrite, pointant vers des pages ASPX
- Rendre 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 peuvent partager aucun balisage avec les modèles Razor, j'ai dû réécrire le balisage d'en-tête et de pied de page standard de notre site Web pour un aspect cohérent.
- Les pages * .aspx sont accessibles directement en cliquant sur leurs URL
Il existe des solutions de contournement pour ces problèmes, mais je n'étais pas suffisamment préoccupé par eux pour faire un travail supplémentaire.
J'espère que cela aide tout le monde!