Over a million developers have joined DZone.

Best Practices for Error Handling in ASP.NET MVC

DZone's Guide to

Best Practices for Error Handling in ASP.NET MVC

In this post, we take a look at some best practices you can employ when setting up error handling in your ASP.NET MVC application.

· Web Dev Zone ·
Free Resource

Jumpstart your Angular applications with Indigo.Design, a unified platform for visual design, UX prototyping, code generation, and app development.

Error handling is an important part of any application. ASP.NET provides several different ways to handle errors. In this article, we will review MVC error handling best practices.

Between .NET, ASP.NET, and MVC there are several potential ways to handle application errors.

  • Web.Config customErrors
  • MVC HandleErrorAttribute
  • Controller.OnException method
  • HttpApplication Application_Error event
  • Collect exceptions via .NET profiling with Retrace

There are some pros and cons to all of these ways to handle errors. You probably need to use a combination of them to properly handle and log errors.

There are two critical things that you need accomplish with error handling:

  1. Gracefully handle errors and show your users a friendly error page.
  2. Logging errors so that you are aware of them and can monitor them.

Must Have: Global Error Page With Web.Config <customErrors>

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.

    <customErrors mode="On" defaultRedirect="~/ErrorHandler/Index">
        <error statusCode="404" redirect="~/ErrorHandler/NotFound"/>

Use MVC HandlerErrorAttribute to Customize Responses

HandleErrorAttribute inherits from the 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.

When to Use HandleErrorAttribute

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 specific MVC controller or action method. Specifying an error page in your Web.Config <customErrors> works ideally for a universal error page. 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 HandleErrorAttribute is it doesn’t provide a way to log the exception!

Use the MVC Controller OnException to Customize Responses

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!!

      //Redirect or return a view, but not both.
      filterContext.Result = RedirectToAction("Index", "ErrorHandler");
      // OR 
      filterContext.Result = new ViewResult
         ViewName = "~/Views/ErrorHandler/Index.cshtml"

When to Use OnException for MVC Error Handling

If you want a way to present your users 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.

Use HttpApplication Application_Error as Global Exception Handler

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()

   protected void Application_Error()
      var ex = Server.GetLastError();
      //log the error!

When to Use Application_Error

Always! HttpApplication’s Error even provides the best mechanism to collect and log all unhandled application errors.

Collect All .NET Exceptions With Stackify Retrace

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 can be configured to receive all exceptions ever thrown, even if they are handled and discarded. Retrace doesn’t require any code changes either!

MVC Error Handling

Screenshot from Retrace

Summary on MVC Error Handling

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.

Take a look at an Indigo.Design sample application to learn more about how apps are created with design to code software.

mvc ,error handling ,c# ,asp.net ,web dev

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}