How easy would our lives be, as programmers, if our applications behaved correctly 100% of the time? Unfortunately, that’s not the case: things go wrong, often in serious ways.
In order to offer the user the best possible experience—and also understand what went wrong so you can fix it—your application needs to handle its errors, and that’s why error handling is an important part of any application.
Most web frameworks provide ways for their users to handle errors, and ASP.NET is no exception. In this article, we will review MVC error handling best practices.
We’ll start by covering some ASP.NET MVC fundamentals. Then, we move on to explain why handling errors is essential in most non-trivial applications and give examples of common errors you might encounter in your web app.
Finally, we move on to discuss five ways in which you can do error handling in ASP.NET MVC. Let’s get started!
First of all, let’s cover some MVC fundamentals. What is MVC, and why should you care about it?
MVC stands for Model-View-Controller. It’s a design pattern developers use to manage the user interface of their applications in such a way that different concerns (user output, connection to the database) are kept segregated so they can be easily managed.
ASP.NET MVC, in a nutshell, it’s a web framework that implements MVC and is part of .NET.
Writing an application and releasing it, despite not being a walk in the park, is just the first step in a never-ending journey. The real challenge is to maintain and evolve an application once it’s deployed.
Once an application is in production, “anything” could happen. And unfortunately, bad things do happen quite a lot. When they do, your code needs to be able to deal graciously with such problems, and that’s where error handling comes in handy.
Through error handling, an application developer can ensure the users get a consistent experience even in the face of failure. Also, a great error-handling policy can be used to generate logs and other types of instrumentation so that developers can, later on, investigate in order to discover the root cause of the problem and fix it.
What are some errors that could need handling in web applications? Here’s a non-exhaustive list:
Between .NET, ASP.NET, and MVC there are several potential ways to handle application errors.
There are some pros and cons to all of these ways to handle errors. You probably need to use a combination of them to handle properly and log errors.
There are two critical things that you need to accomplish with error handling:
The last thing you ever want your users to see is a “yellow screen of death” type error. If you don’t know what that is, I’m referring the standard yellow ASP.NET error screen.
For any application, I would always recommend specifying a custom error page in your Web.Config. Worst case scenario, your users will see this page if an unhandled exception occurs.
<system.web> <customErrors mode="On" defaultRedirect="~/ErrorHandler/Index"> <error statusCode="404" redirect="~/ErrorHandler/NotFound"/> </customErrors> <system.web/>
MORE: How to Use Web.Config customErrors for ASP.NET
The HandleErrorAttribute inherits from FilterAttribute and can be applied to an entire controller or individual controller action methods.
It can only handle 500-level errors that happen within an MVC action method. It does not track exceptions that help outside of the MVC pipeline. Exceptions may occur in other HTTP modules, MVC routing, etc.
Since it does not provide a way to collect all exceptions that could ever happen, it is a bad solution for a global unhandled error handler.
It works perfectly for tailoring specific error pages for a particular MVC controller or action method and specifying an error page in your Web.config <customErrors> works ideal for a universal error page. The HandleErrorAttribute gives you fine-grained control if you need it.
Note: HandleErrorAttribute requires customErrors to be enabled in your Web.Config.
For example, if you wanted to show a particular MVC view when a SqlException happens, you can do it with the code below:
[HandleError(ExceptionType = typeof(SqlException), View = "SqlExceptionView")] public string GetClientInfo(string username) { return "true"; }
The problem with HandleErrorAttribute is it doesn’t provide a way to log the exception!
OnException is similar to HandleErrorAttribute but provides more flexibility. It works with all HTTP status codes, and not just 500-level responses. It also gives you the ability to log the errors!
public class UserMvcController : Controller { protected override void OnException(ExceptionContext filterContext) { filterContext.ExceptionHandled = true; //Log the error!! _Logger.Error(filterContext.Exception); //Redirect or return a view, but not both. filterContext.Result = RedirectToAction("Index", "ErrorHandler"); // OR filterContext.Result = new ViewResult { ViewName = "~/Views/ErrorHandler/Index.cshtml" }; } }
If you want a way to present your users with custom MVC views or custom log exceptions, OnException is a good solution for you. It provides more flexibility than HandleErrorAttribute and does not require customErrors to be enabled in your Web.Config file.
Note: OnException gets called for all HTTP status codes. So be careful how you handle simple issues like a 404 caused by a bad URL.
So far we have covered three different ways to customize the response that your users see if an exception occurs. Only within OnException can you potentially log exceptions.
To log all unhandled exceptions that may occur within your application, you should implement a basic error logging code as shown below.
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } protected void Application_Error() { var ex = Server.GetLastError(); //log the error! _Logger.Error(ex); } }
Always! HttpApplication’s Error even provides the best mechanism to collect and log all unhandled application errors.
Stackify’s APM solution, Retrace, taps into the .NET profiling APIs to track the performance of your app down to the code level. As part of that, it can automatically collect all unhandled exceptions or be configured to receive all exceptions ever thrown, even if they are handled and discarded. Retrace doesn’t require any code changes either!
Retrace allows you to view and monitor all of your application errors. Check out our error monitoring features to learn more.
There are several ways to do MVC error handling. You should always specify a default error page via your web.config <customErrors> and log unhandled exceptions that get called back to your HttpApplication Error method.
You can use HandleErrorAttribute or OnException to provide fine-grained control of how you display error type messages to your users.
If you want to track all of your application exceptions, be sure to check our Retrace and our error monitoring features. You can also view all application exceptions on your workstation for free with our free profiler, Prefix.
More Resources:
If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]