U
U
up2016-06-01 10:11:50
ASP.NET
up, 2016-06-01 10:11:50

How to handle all errors (trapped and uncaught) in ASP.Net MVC?

There is a large ASP.Net MVC application that accesses a bunch of services. The behavior of services is not always stable, so there are a lot of try/catch blocks in the code.
There is a need to additionally process all exceptions: search the database and, depending on the search results, perform further actions.
Question: how to impose processing on all errors (trapped and uncaught) in ASP.Net MVC? Is there some mechanism or write a new method in each catch block?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
Sanostee, 2016-06-01
@andrewpianykh

I prefer the following approach:

public class ErrorController
{
  public virtual ActionResult BadRequest()
  {
    return View();
  }

  public virtual ActionResult Forbidden()
  {
    return View();
  }

  public virtual ActionResult Index()
  {
    return View();
  }

  public virtual ActionResult NotFound()
  {
    return View();
  }
}

public class ExtHandleErrorAttribute : HandleErrorAttribute
{
  //private readonly ILogger logger;

  public ExtHandleErrorAttribute(/*ILogger logger*/)
  {
    //this.logger = logger;
  }

  public override void OnException(ExceptionContext filterContext)
  {
    if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
    {
      return;
    }

    if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)
    {
      return;
    }

    if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
    {
      return;
    }

    if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
    {
      filterContext.Result = new JsonResult
      {
        JsonRequestBehavior = JsonRequestBehavior.AllowGet,
        Data = new
        {
          error = true,
          message = filterContext.Exception.Message
        }
      };
    }
    else
    {
      var controllerName = (string)filterContext.RouteData.Values["controller"];
      var actionName = (string)filterContext.RouteData.Values["action"];
      var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

      filterContext.Result = new ViewResult
      {
        ViewName = View,
        MasterName = Master,
        ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
        TempData = filterContext.Controller.TempData
      };
    }

    //var e = filterContext.Exception;
    //logger.Error(e, e.Message);

    filterContext.ExceptionHandled = true;
    filterContext.HttpContext.Response.Clear();
    filterContext.HttpContext.Response.StatusCode = 500;
    filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
  }
}

public class FilterConfig
{
  public static void RegisterGlobalFilters(GlobalFilterCollection filters)
  {
    var extHandleErrorAttribute = DependencyResolver.Current.GetService<ExtHandleErrorAttribute>();// new ExtHandleErrorAttribute();
    filters.Add(extHandleErrorAttribute);
  }
}

protected void Application_Error(object sender, EventArgs e)
{
  var httpContext = ((MvcApplication)sender).Context;

  var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
  var currentController = " ";
  var currentAction = " ";

  if (currentRouteData != null)
  {
    if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
    {
      currentController = currentRouteData.Values["controller"].ToString();
    }

    if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
    {
      currentAction = currentRouteData.Values["action"].ToString();
    }
  }

  var ex = Server.GetLastError();

  var controller = new ErrorController();
  var routeData = new RouteData();
  var action = "Index";

  if (ex is HttpException)
  {
    var httpEx = ex as HttpException;

    switch (httpEx.GetHttpCode())
    {
      case 404:
        action = "NotFound";
        break;

      case 403:
        action = "Forbidden";
        break;

      case 400:
        action = "BadRequest";
        break;

      default:
        action = "Index";
        //var logger = DependencyResolver.Current.GetService<ILogger>();
        //logger.Error(ex, ex.Message);
        break;
    }
  }

  httpContext.ClearError();
  httpContext.Response.Clear();
  httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500;
  httpContext.Response.TrySkipIisCustomErrors = true;
  routeData.Values["controller"] = "Error";
  routeData.Values["action"] = action;

  controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction);
  ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}

<httpErrors>
  <remove statusCode="400" subStatusCode="-1" />
  <remove statusCode="403" subStatusCode="-1" />
  <remove statusCode="502" subStatusCode="-1" />
  <remove statusCode="501" subStatusCode="-1" />
  <remove statusCode="500" subStatusCode="-1" />
  <remove statusCode="404" subStatusCode="-1" />
  <error statusCode="400" prefixLanguageFilePath="" path="/Error/BadRequest" responseMode="ExecuteURL" />
  <error statusCode="404" prefixLanguageFilePath="" path="/Error/NotFound" responseMode="ExecuteURL" />
  <error statusCode="500" prefixLanguageFilePath="" path="/Error" responseMode="ExecuteURL" />
  <error statusCode="501" prefixLanguageFilePath="" path="/Error" responseMode="ExecuteURL" />
  <error statusCode="502" prefixLanguageFilePath="" path="/Error" responseMode="ExecuteURL" />
  <error statusCode="403" prefixLanguageFilePath="" path="/Error/Forbidden" responseMode="ExecuteURL" />
</httpErrors>

T
Tsiren Naimanov, 2016-06-01
@ImmortalCAT

here through the attribute goes

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question