ASP.NET MVC中异常处理&自定义错误页详析

2019-05-25 13:18:21于海丽

一、应用场景

对于B/S应用程序,在部署到正式环境运行的过程中,很有可能出现一些在前期测试过程中没有发现的一些异常或者错误,或者说只有在特定条件满足时才会发生的一些异常,对于使用ASP.NET MVC开发的应用程序站点,在部署到IIS上后,如果开发人员未对程序进行错误处理,那么一旦程序出现未处理的错误或异常,用户将看到一个让人感到及其困惑的错误堆栈跟踪页面,使得站点的用户体验下降,从程序的角度上来说,不做自定义错误处理也不利于程序出问题时的根源查找,因为很多时候有些错误只在特定条件下满足时才重现,一旦错过,可能就需要花大量时间去测试来重现问题,如果此时开发人员有对程序中的运行时异常进行日志记录,那么或许将提供一些有价值的错误根源信息,下面我将向下大家讲解如何实现自定义异常处理并跳转到友好的错误提示页面。

二、异常处理&自定义错误页

1、通过异常过滤器 实现异常处理和自定义错误页

asp.net mvc 提供了 异常过滤器 的方式来实现当执行controller中某个action方法时抛出了未处理的异常时的捕捉,mvc中的异常过滤器是以特性(Attribute)的形式存在的,定义一个自定义异常过滤器只需要两个步骤:

1、定义一个类,继承FilterAttribute类,并实现IExceptionFilter接口 2、应用自定义异常过滤器至指定的 action方法 或 controller类 或 全局应用。

异常过滤器代码

using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Blog20180413.Filters
{
 public class CustomExceptionFilterAttribute : FilterAttribute, IExceptionFilter
 {
 //log4net组件,用于日志记录。
 static readonly ILog log = LogManager.GetLogger(typeof(CustomExceptionFilterAttribute));
 public void OnException(ExceptionContext filterContext)
 {
  //对捕获到的异常信息进行日志记录,方便开发人员排查问题。
  log.Error("应用程序异常", filterContext.Exception);

  //跳转到自定义的错误页,增强用户体验。
  ActionResult result = new ViewResult() { ViewName = "CustomErrorPage" };
  filterContext.Result = result;
  //异常处理结束后,一定要将ExceptionHandled设置为true,否则仍然会继续抛出错误。
  filterContext.ExceptionHandled = true;
 }
 }
}

使用异常过滤器

using Blog20180413.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Blog20180413.Controllers
{
 public class TestExceptionHandleController : Controller
 {
 [CustomExceptionFilter]
 public ActionResult Index()
 {
  string str = string.Empty;
  //将抛出转换异常
  int result = int.Parse(str);
  return View();
 }
 }
}

注意:

第二个步骤中提到,可以将自定义异常过滤器 只应用到 action或者controller,如果只想将指定的异常过滤器以特性的形式应用到指定的一个或者多个controller或者action,而不想应用到所有的controller或者action,那么必须将该异常过滤器继承FilterAttribute类,这是因为mvc框架是通过FilterAttributeFilterProvider.GetFilters来获取标记在指定controller或者action上的异常过滤器特性的,而GetFilters内部逻辑要求必须继承自FilterAttribute类。