Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.net MVC - Custom HandleError Filter - Specify View based on Exception Type

I am inheriting the HandleErrorAttribute in my MVC application so I can log the error:

public class HandleAndLogErrorAttribute : HandleErrorAttribute {     public override void OnException(ExceptionContext filterContext)     {         base.OnException(filterContext);          if( filterContext.Exception != null )         {             // log here         }     } } 

I'm adding this as a global filter:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) {     filters.Add(new HandleAndLogErrorAttribute()); } 

Is it possible to specify a custom view for specific exception types as well? For example:

if( filterContext.Exception is DivideByZeroException ) {     // how do i specify that the view should be DivideByZero? } 
like image 366
Dismissile Avatar asked Nov 15 '11 23:11

Dismissile


People also ask

How do I create a custom exception filter?

Right-click on create method and add view. Add the CustomExceptionHandlerFilter class for creating a custom exception handler. Implements FilterAttribute and IExceptionFilter and overrides the OnException method. Open App_Start folder inside the App_start folder contains FilterConfig class.

How do I use exception filters?

Implement the OnException method and add your custom logic into the method. Hence, the code will look, as shown below. Apply the class name as an attribute on the controller class. Add an exception in the controller Index method.


1 Answers

  1. Create a new filter which inherits HandleErrorAttribute (or implements IExceptionFilter directly)
  2. Register it in global.asax (by replacing filters.Add(new HandleError());):

Here is a filter that I've created that tries to find a view per specific HTTP status code:

public class MyErrorHandler : FilterAttribute, IExceptionFilter {     public void OnException(ExceptionContext filterContext)     {         if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)             return;          var statusCode = (int) HttpStatusCode.InternalServerError;         if (filterContext.Exception is HttpException)         {             statusCode = filterContext.Exception.As<HttpException>().GetHttpCode();         }         else if (filterContext.Exception is UnauthorizedAccessException)         {             //to prevent login prompt in IIS             // which will appear when returning 401.             statusCode = (int)HttpStatusCode.Forbidden;          }         _logger.Error("Uncaught exception", filterContext.Exception);          var result = CreateActionResult(filterContext, statusCode);         filterContext.Result = result;          // Prepare the response code.         filterContext.ExceptionHandled = true;         filterContext.HttpContext.Response.Clear();         filterContext.HttpContext.Response.StatusCode = statusCode;         filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;     }      protected virtual ActionResult CreateActionResult(ExceptionContext filterContext, int statusCode)     {         var ctx = new ControllerContext(filterContext.RequestContext, filterContext.Controller);         var statusCodeName = ((HttpStatusCode) statusCode).ToString();          var viewName = SelectFirstView(ctx,                                        "~/Views/Error/{0}.cshtml".FormatWith(statusCodeName),                                        "~/Views/Error/General.cshtml",                                        statusCodeName,                                        "Error");          var controllerName = (string) filterContext.RouteData.Values["controller"];         var actionName = (string) filterContext.RouteData.Values["action"];         var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);         var result = new ViewResult                          {                              ViewName = viewName,                              ViewData = new ViewDataDictionary<HandleErrorInfo>(model),                          };         result.ViewBag.StatusCode = statusCode;         return result;     }      protected string SelectFirstView(ControllerContext ctx, params string[] viewNames)     {         return viewNames.First(view => ViewExists(ctx, view));     }      protected bool ViewExists(ControllerContext ctx, string name)     {         var result = ViewEngines.Engines.FindView(ctx, name, null);         return result.View != null;     } } 
like image 184
jgauffin Avatar answered Oct 11 '22 08:10

jgauffin