Lorsqu’une exception est générée par votre propre code appelé à partir d’une action dans un contrôleur, comment doit-elle être gérée? Je vois beaucoup d’exemples de meilleures pratiques pour lesquelles il n’y a pas de déclarations try-catch. Par exemple, accéder à des données depuis un référentiel:
public ViewResult Index() { IList customModels = _customModelRepository.GetAll(); return View(customModels); }
Il est clair que ce code peut générer une exception si l’appel est adressé à une firebase database à laquelle elle ne peut accéder et si nous utilisons un ORM comme Entity Framework, par exemple.
Cependant, tout ce que je peux voir, c’est que l’exception bouillonne et affiche un message d’erreur désagréable à l’intention de l’utilisateur.
Je connais l’atsortingbut HandleError mais je comprends qu’il est principalement utilisé pour vous redirect vers une page d’erreur si une exception non gérée se produit.
Bien sûr, ce code pourrait être encapsulé dans un try-catch mais ne se sépare pas bien, surtout si vous avez plus de logique:
public ViewResult Index() { if (ValidationCheck()) { IList customModels = new List(); try { customModels = _customModelRepository.GetAll(); } catch (SqlException ex) { // Handle exception } if (CustomModelsAreValid(customModels)) // Do something else // Do something else } return View(); }
Auparavant, j’avais extrait tout le code susceptible de générer des exceptions, telles que les appels de firebase database, dans une classe DataProvider qui traite les erreurs et renvoie les messages permettant d’afficher des messages à l’utilisateur.
Je me demandais quelle était la meilleure façon de gérer cela? Je ne veux pas toujours revenir à une page d’erreur car certaines exceptions ne devraient pas le faire. Au lieu de cela, un message d’erreur à l’utilisateur devrait être affiché avec une vue normale. Ma méthode précédente était-elle correcte ou existe-t-il une meilleure solution?
Je fais trois choses pour afficher des messages plus conviviaux:
EDIT: Je pensais mentionner l’API Web ASP.NET car elle est étroitement liée. Étant donné que le consommateur de points de terminaison API Web ne sera pas nécessairement un navigateur, j’aime traiter les erreurs un peu différemment. J’utilise toujours “FriendlyException” (n ° 2 ci-dessus), mais au lieu de redirect vers un ErrorController, je laisse simplement tous mes points de terminaison renvoyer un type de type de base contenant une propriété Error. Ainsi, si une exception remonte jusqu’aux contrôleurs de l’API Web, je m’assure de coller cette erreur dans la propriété Error de la réponse de l’API. Ce message d’erreur sera soit le message convivial des classes sur lesquelles le contrôleur d’API s’appuie, soit un message générique si le type d’exception n’est pas une exception FriendlyException. Ainsi, le client consommateur peut simplement vérifier si la propriété Error de la réponse de l’API est vide ou non. Afficher un message si l’erreur est présente, procéder comme d’habitude sinon. La bonne chose est que, en raison du concept de message convivial, le message peut être beaucoup plus significatif pour l’utilisateur qu’un message d’erreur générique “Erreur!” message. J’utilise cette stratégie lorsque j’écris des applications mobiles avec Xamarin, où je peux partager mes types C # entre mes services Web et mon application iOS / Android.
Avec Asp.Net MVC, vous pouvez également remplacer la méthode OnException pour votre contrôleur.
protected override void OnException(ExceptionContext filterContext) { if (filterContext.ExceptionHandled) { return; } filterContext.Result = new ViewResult { ViewName = ... }; filterContext.ExceptionHandled = true; }
Cela vous permet de redirect vers une page d’erreur personnalisée avec un message faisant référence à l’exception si vous le souhaitez.
J’ai utilisé une substitution OnException car plusieurs projets font référence à un projet avec un contrôleur qui gère les erreurs:
Sécurité / HandleErrorsController.cs
protected override void OnException(ExceptionContext filterContext) { MyLogger.Error(filterContext.Exception); //method for log in EventViewer if (filterContext.ExceptionHandled) return; filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; filterContext.Result = new JsonResult { Data = new { Success = false, Error = "Please report to admin.", ErrorText = filterContext.Exception.Message, Stack = filterContext.Exception.StackTrace }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; filterContext.ExceptionHandled = true; }
Toutes les questions de ce type ne sont pas très constructives, car la réponse est toujours “cela dépend”, car il existe de nombreuses manières de traiter le traitement des erreurs.
Beaucoup de gens aiment utiliser la méthode HandleError, car toute exception est fondamentalement non récupérable. Je veux dire, qu’allez-vous faire si vous ne pouvez pas retourner les objects? Vous allez leur montrer une erreur de toute façon, non?
La question est de savoir comment vous voulez leur montrer l’erreur. Si leur montrer une page d’erreur est acceptable, HandleError fonctionne correctement et fournit un emplacement facile pour consigner l’erreur. Si vous utilisez Ajax ou voulez quelque chose de plus sophistiqué, vous devez développer un moyen de le faire.
Vous parlez d’une classe DataProvider. C’est fondamentalement ce que votre référentiel est. Pourquoi ne pas intégrer cela dans votre référentiel?