Tuesday 24 July 2018

MVC Error Handling


4 Ways to do MVC Error Handling

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

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.
<system.web>
    <customErrors mode="On" defaultRedirect="~/ErrorHandler/Index">
        <error statusCode="404" redirect="~/ErrorHandler/NotFound"/>
    </customErrors>
<system.web/>

Use MVC HandlerErrorAttribute to Customize Responses
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.
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 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!

Use 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!!
      _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"
      };
   }
}

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.
public class BaseController : Controller

    {

        protected override void OnException(ExceptionContext filterContext)

        {

            filterContext.ExceptionHandled = true;

            ViewData["Data"] = filterContext.Exception.Message.ToString();

            filterContext.Result = new ViewResult { ViewData = this.ViewData, ViewName = "Error" };

            base.OnException(filterContext);

        }

    }
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 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);
   }
}
When to Use Application_Error
Always! HttpApplication’s Error even provides the best mechanism to collect and log all unhandled application errors.




No comments:

Post a Comment