Handling all exceptions in controllers using the attribute
We all know that in ASP.NET MVC there is such an attribute
But nowhere, in the same MSDN it is not said (poke me with your nose, give the link where it is written, if I looked) that it only handles exceptions that set the server’s response code to 500.
Looking at the source code is
I don’t know about you, but it’s more convenient for me when an exception occurs that users see a special page for this, and not the “yellow page of death” or even how the browser displays a standard page for it with the server response code (it depends on the settings in Web.config, but more on that later).
Creating your own analogue
So, we found out that the standard
You can, of course, create a class by inheriting it from the interface
To begin with, I will say that this is standard code
Actually what he does:
Our class is ready, now we will replace the standard attribute with ours. We do this through global filters so that we don’t write it to every controller or controller action. In this case, this is not critical, but in reality it can come in handy. So, we go to Global.asax.cs and set instead of the standard filter, our just created attribute:
Now, to make sure that our filter works and passes the necessary data to
And add the following line to the section in Web.config (which is located in the root)
With this line, we enable custom error handling, more precisely, custom error pages.
Now we need to throw an exception, I will do this in the action of the standard controller (created by the studio):
All! We start the project, go to the "About" section and see that our attribute worked correctly.

HandleErrorAttribute
, which as stated in MSDNRepresents an attribute used to handle an exception raised by an action method.
But nowhere, in the same MSDN it is not said (
Looking at the source code is
HandleErrorAttribute
easy to verify. The following lines are there:// 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 about you, but it’s more convenient for me when an exception occurs that users see a special page for this, and not the “yellow page of death” or even how the browser displays a standard page for it with the server response code (it 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
is not suitable for us, well, let's create our own. You can, of course, create a class by inheriting it from the interface
IExceptionFilter
, but in general, we are satisfied with the standard behavior HandleErrorAttribute
if it handled all exceptions. And since almost everything suits us, our class will inherit from the objectionable to us 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(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 standard code
HandleErrorAttribute
, with the exception of a few lines that check for HttpStatusCode
. Actually what he does:
- Checks input parameters for validity
- Checks if included
customErrors
- Fills a class with data
HandleErrorInfo
- Creates a new one
ViewResult
, fills with data and assigns instead of the current - Clears server errors and sets the server response code
Our class is ready, now we will replace the standard attribute with ours. We do this through global filters so that we don’t write it to every controller or controller action. In this case, this is not critical, but in reality it can come in handy. So, we go to Global.asax.cs and set instead of the standard filter, our just created attribute:
filters.Add(new HandleAllErrorAttribute());
Test
Now, to make sure that our filter works and passes the necessary data to
View
, we ’ll slightly modify the standard ~ / Views / Shared / Error.cshtml :@model System.Web.Mvc.HandleErrorInfo
@{
ViewBag.Title = "Error";
}
Sorry, an error occurred while processing your request.
@Model.Exception.Message
And add the following line to the section in Web.config (which is located in the root)
System.Web
:
With this line, we enable custom error handling, more precisely, custom error pages.
Now we need to throw an exception, I will do this in the action of the standard controller (created by the studio):
public ActionResult About()
{
throw new HttpException(403, "Доступ запрещён!");
return View();
}
All! We start the project, go to the "About" section and see that our attribute worked correctly.
