📜 ⬆️ ⬇️

Handling all exceptions in controllers using an attribute

We all know that in ASP.NET MVC there is an attribute HandleErrorAttribute , which, as stated in MSDN
Represents an attribute used to handle an exception that is called by an action method.

But nowhere, in the same MSDN it is not said ( poke my nose at the link where it is written, if I looked) that it only handles exceptions that set the server response code to 500.

Looking at the source code of HandleErrorAttribute it is easy to see this. There are the following lines:

 // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method), // ignore it. if (new HttpException(null, exception).GetHttpCode() != 500) { return; } 

I don’t know how you are, but it’s more convenient for me when an exception occurs that users see a special page for this, and not a “yellow death page” or even as a browser displays a standard page with a server response code (depends on the settings in Web.config but more on that later).
')

Creating your own analogue HandleErrorAttribute


So, we found out that the standard HandleErrorAttribute does not suit us, well, let's create our own.

You can, of course, create a class by inheriting it from the IExceptionFilter interface, but we are generally satisfied with the behavior of the standard HandleErrorAttribute if it handles all exceptions. And since we are almost satisfied with everything, our class will inherit from the HandleErrorAttribute we don’t HandleErrorAttribute .

 public class HandleAllErrorAttribute : HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } // If custom errors are disabled, we need to let the normal ASP.NET exception handler // execute so that the user can see useful debugging information. if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) { return; } Exception exception = filterContext.Exception; if (!ExceptionType.IsInstanceOfType(exception)) { return; } string controllerName = (string)filterContext.RouteData.Values["controller"]; string actionName = (string)filterContext.RouteData.Values["action"]; HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName); filterContext.Result = new ViewResult { ViewName = View, MasterName = Master, ViewData = new ViewDataDictionary<HandleErrorInfo>(model), TempData = filterContext.Controller.TempData }; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = new HttpException(null, exception).GetHttpCode(); // Certain versions of IIS will sometimes use their own error page when // they detect a server error. Setting this property indicates that we // want it to try to render ASP.NET MVC's error page instead. filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; } } 

To begin with, I will say that this is the code of the standard HandleErrorAttribute , with the exception of a few lines that check for HttpStatusCode .

Actually, what he does:


Our class is ready, now let's replace the standard attribute with ours. We do this through global filters so that we don’t write it to each controller or controller action. In this case, it is not critical, but in reality it can be useful. So, let's go to Global.asax.cs and write instead of the standard filter, our newly created attribute:

 filters.Add(new HandleAllErrorAttribute()); 


Test


Now, to make sure that our filter works and passes the necessary data to the View , let's change the standard ~ / Views / Shared / Error.cshtml :

 @model System.Web.Mvc.HandleErrorInfo @{ ViewBag.Title = "Error"; } <h2> Sorry, an error occurred while processing your request. </h2> <h3>@Model.Exception.Message</h3> 

And add the following line to the System.Web section in the Web.config (which is in the root):

 <customErrors mode="On" defaultRedirect="Error" /> 

This line we include custom error handling, more precisely, custom error pages.

Now we need to raise an exception, I will do it in the action of a standard controller (created by the studio):

 public ActionResult About() { throw new HttpException(403, " !"); return View(); } 

Everything! We start the project, go to the section “About” and see that our attribute has worked correctly.


Source: https://habr.com/ru/post/137672/


All Articles