J’ai un code dans l’événement Application_Error
du fichier global.asax
qui s’exécute lorsqu’une erreur se produit et me transmet les détails de l’erreur par courrier électronique.
void Application_Error(object sender, EventArgs e) { var error = Server.GetLastError(); if (error.Message != "Not Found") { // Send email here... } }
Cela fonctionne bien lorsque je l’exécute dans Visual Studio, mais lorsque je publie sur notre serveur en direct, l’événement Application_Error
ne se déclenche pas.
Après quelques tests, je peux obtenir le déclenchement de Application_Error
lorsque je définis customErrors="Off"
, mais le remettre à customErrors="On"
arrête le déclenchement de l’événement.
Quelqu’un peut-il suggérer pourquoi Application_Error
ne se déclenche pas lorsque les customErrors
sont activés dans le web.config
?
METTRE À JOUR
Étant donné que 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 méthode 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 HandleErrorAtsortingbute()); // 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 le Global.asax.cs
. Cette logique est utilisée pour mapper des itinéraires et enregistrer des filtres. Par défaut, il n’enregistre qu’un seul filtre: un filtre HandleErrorAtsortingbute
. Lorsque customErrors est activé (ou via des requêtes distantes lorsqu’il est défini sur RemoteOnly), HandleErrorAtsortingbute indique à MVC de rechercher une vue d’erreur et n’appelle jamais la méthode Application_Error()
. Je n’ai pas trouvé 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, supprimez simplement la ligne qui enregistre le filtre HandleErrorAtsortingbute.
Maintenant, le problème est le suivant: comment configurer les CustomErrors pour obtenir ce que vous voulez …
La section customErrors par défaut est redirectMode="ResponseRedirect"
. Vous pouvez également spécifier que l’atsortingbut defaultRedirect soit un itinéraire MVC. J’ai créé un ErrorController qui était très simple et a changé mon site web.config pour ressembler à ceci …
web.config
Le problème avec cette solution est qu’il effectue une redirection 302 vers vos URL d’erreur, puis ces pages répondent par un code d’état 200. Cela amène Google à indexer les pages d’erreur, ce qui est mauvais. Il n’est pas très conforme aux spécifications HTTP. Ce que je voulais faire n’était pas de redirect et 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 , mais 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 200 mais, au moins, il n’a pas été redirigé. J’ai ensuite 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 …
Ce bloc indique à la page à servir avec le code d’état correct. De façon grossière, sur la page PageNotFound.aspx, j’ai plutôt utilisé HttpStatusCode.NotFound
. J’ai changé mon web.config pour ressembler à ceci …
Tout a parfaitement fonctionné!
Résumé:
filters.Add(new HandleErrorAtsortingbute());
Application_Error()
pour consigner les exceptions Il y a quelques inconvénients que j’ai remarqués avec cette solution.
Il y a des solutions pour ces problèmes, mais ils ne me préoccupaient pas suffisamment pour faire un travail supplémentaire.
J’espère que cela aide tout le monde!
J’ai résolu ce problème en créant un filtre d’exception et en enregistrant l’erreur à la place de Application_Error. Tout ce que vous avez à faire est d’append un appel dans RegisterGlobalFilters
log4netExceptionFilter.cs
using System using System.Web.Mvc; public class log4netExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext context) { Exception ex = context.Exception; if (!(ex is HttpException)) //ignore "file not found" { //Log error here } } }
Global.asax.cs
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new log4netExceptionFilter()); //must be before HandleErrorAtsortingbute filters.Add(new HandleErrorAtsortingbute()); }
J’ai trouvé un article décrivant une manière beaucoup plus propre de créer des pages d’erreur personnalisées dans une application Web MVC3, ce qui n’empêche pas la possibilité de consigner les exceptions.
La solution consiste à utiliser l’élément
section
.
J’ai configuré mon Web.config comme ça …
J’ai également configuré customErrors
pour avoir mode="Off"
(comme suggéré par l’article).
Cela rend les réponses remplacées par les actions d’un ErrorController. Voici ce contrôleur:
public class ErrorController : Controller { public ActionResult Index() { return View(); } public ActionResult NotFound() { return View(); } }
Les vues sont très simples, je viens d’utiliser la syntaxe Razor standard pour créer les pages.
Cela seul devrait suffire pour que vous utilisiez des pages d’erreur personnalisées avec MVC.
J’avais aussi besoin de consigner les exceptions, alors j’ai volé la solution de Mark consistant à utiliser un filtre d’exception personnalisé …
public class ExceptionPublisherExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext exceptionContext) { var exception = exceptionContext.Exception; var request = exceptionContext.HttpContext.Request; // log stuff } }
La dernière chose que vous devez faire est d’enregistrer le filtre d’exception dans votre fichier Global.asax.cs :
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new ExceptionPublisherExceptionFilter()); filters.Add(new HandleErrorAtsortingbute()); }
Cela semble être une solution beaucoup plus propre que ma réponse précédente et fonctionne aussi bien que je peux le dire. Je l’aime particulièrement parce que je n’avais pas l’impression de me battre contre le framework MVC; cette solution l’utilise en fait!
En cas d’utilisation d’ ASP.NET MVC5
public class ExceptionPublisherExceptionFilter : IExceptionFilter { private static Logger _logger = LogManager.GetCurrentClassLogger(); public void OnException(ExceptionContext exceptionContext) { var exception = exceptionContext.Exception; var request = exceptionContext.HttpContext.Request; // HttpException httpException = exception as HttpException; // Log this exception with your logger _logger.Error(exception.Message); } }
Vous pouvez le trouver dans FilterConfig.cs
du dossier App_Start
.
J’aime la réponse de Mark avec le filtre d’exception, mais une autre option, si tous vos contrôleurs dérivent du même contrôleur de base, consiste à simplement remplacer OnException dans votre contrôleur de base. Vous pouvez faire votre journalisation et emailing là. Cela a l’avantage de pouvoir utiliser toutes les dépendances que vous avez déjà injectées dans votre contrôleur de base avec votre conteneur IoC.
Vous pouvez toujours utiliser votre IoC avec un IExceptionFilter, mais il est un peu plus compliqué de configurer vos liaisons.
Autant que je sache, vous transmettez le contrôle à la page spécifiée dans le paramètre url et votre notification d’événement sera placée ici, plutôt que Application_Error
Beaucoup d’informations peuvent être trouvées ici: http://support.microsoft.com/kb/306355
Pour contourner cela, j’ai fini par laisser les customerrors désactivées et gérer toutes les erreurs de l’événement Application_Error dans global.asax. C’est un peu délicat avec MVC car je ne voulais pas retourner une redirection 301, je voulais retourner des codes d’erreur appropriés. Plus de détails peuvent être consultés sur mon blog à l’ adresse http://www.wduffy.co.uk/blog/using-application_error-in-asp-net-mvcs-global-asax-to-handle-errors/ mais le code final est énumérés ci-dessous…
void Application_Error(object sender, EventArgs e) { var error = Server.GetLastError(); var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500; if (code != 404) { // Generate email with error details and send to administrator } Response.Clear(); Server.ClearError(); ssortingng path = Request.Path; Context.RewritePath(ssortingng.Format("~/Errors/Http{0}", code), false); IHttpHandler httpHandler = new MvcHttpHandler(); httpHandler.ProcessRequest(Context); Context.RewritePath(path, false); }
Et voici le contrôleur
public class ErrorsController : Controller { [HttpGet] public ActionResult Http404(ssortingng source) { Response.StatusCode = 404; return View(); } [HttpGet] public ActionResult Http500(ssortingng source) { Response.StatusCode = 500; return View(); } }
Cette entrée de blog m’a aidé:
http://asp-net.vexedlogic.com/2011/04/23/asp-net-maximum-request-length-exceeded/
Si vous utilisez IIS 7.0 ou version ultérieure, vous pouvez modifier votre fichier Web.config pour gérer les demandes trop volumineuses. Il y a quelques mises en garde, mais voici un exemple:
Il y a des détails supplémentaires sur ces éléments de fichier de configuration ici:
http://www.iis.net/ConfigReference/system.webServer/security/requestFiltering/requestLimits
Le code d’état 404.13 est défini comme “Longueur de contenu trop grande”. Une chose importante à noter est que maxAllowedContentLength
est spécifié en octets. Ceci est différent du paramètre maxRequestLength
vous trouvez dans la section
, spécifiée en kilo-octets.
Notez également que l’atsortingbut path
doit être un chemin absolu lorsque responseMode
est Redirect
, ajoutez donc le nom du répertoire virtuel, le cas échéant. Les réponses informatives de Jesse Webb montrent comment procéder avec responseMode="ExecuteURL"
, et je pense que cette approche pourrait également fonctionner.
Cette approche ne fonctionne pas si vous développez à l’aide du serveur de développement Visual Studio (Cassini, le serveur Web intégré à Visual Studio). Je suppose que cela fonctionnerait dans IIS Express, mais je n’ai pas testé cela.
J’avais le même problème où Application_Error()
n’était pas touché. J’ai tout essayé, jusqu’à ce que je traverse ce qui se passait. J’avais un code personnalisé dans un événement ELMAH qui ajoutait JSON à l’e-mail qu’il envoyait, et il y avait une erreur nulle!
La correction de l’erreur interne a permis au code de continuer à l’événement Application_Error()
comme prévu.