异常处理是每一个系统都必要有的功能,在程序出错的时候不会给用户显示莫名其妙的页面,或暴露你的代码的堆栈信息!那么在ASP.NET MVC 如何正确处理异常并记录呢?
答案是可以利用ASP.NET MVC Filter(筛选器)利用AOP的方式 进行全局异常捕获 自定义ExceptionFilter
废话不多说直接上源码
在ASP.NET MVC 根目录新建个文件夹 命名为 Filter
在Filter新建一个Class类 命名为CustomExceptionAttribute,并让它继承FilterAttribute类和IExceptionFilter接口
如下
下面是代码
代码思想为
/// <summary> /// 系统集中异常处理 /// 重写官方默认的HandleErrorAttribute处理 /// </summary> public class CustomExceptionAttribute : FilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { //查看是否已处理异常 if (filterContext.ExceptionHandled == true) { //已处理 直接跳过 return; } else { //记录日志 var log = new ExceptionLogModel(); log.ControllerName = (string)filterContext.RouteData.Values["controller"];//控制器名称 log.ActionName = (string)filterContext.RouteData.Values["action"]; //操作名称 log.LoginUser = "临时测试用户"; //异常操作的用户 log.Url = filterContext.RequestContext.HttpContext.Request.Url.LocalPath; //异常发生的url log.LogLevel = LogLevel.Error; //异常类型 log.Source = filterContext.Exception.Source; //引发异常的对象 log.ErrorMsg = filterContext.Exception.Message; //异常详情信息 log.StackTrace = filterContext.Exception.StackTrace; //异常堆栈信息 log.ExceptionLog(); } //查看是否通过异步请求 bool AjaxReq = filterContext.HttpContext.Request.IsAjaxRequest(); //根据http状态码 跳转到指定的异常页面 var httpException = new HttpException(null, filterContext.Exception); switch (httpException.GetHttpCode()) { case 400: if (!AjaxReq) { ViewResult result = new ViewResult { ViewName = "Page_400", //错误页 MasterName = null, //指定母版页 ViewData = null, //指定模型 TempData = filterContext.Controller.TempData }; filterContext.Result = result; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 400; } else { filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest, filterContext.Exception.Message); } break; case 401: if (!AjaxReq) { ViewResult result = new ViewResult { ViewName = "Page_401", //错误页 MasterName = null, //指定母版页 ViewData = null, //指定模型 TempData = filterContext.Controller.TempData }; filterContext.Result = result; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 401; } else { filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.Unauthorized, "You Must login to perform this operation"); } break; case 403: if (!AjaxReq) { ViewResult result = new ViewResult { ViewName = "Page_403", //错误页 MasterName = null, //指定母版页 ViewData = null, //指定模型 TempData = filterContext.Controller.TempData }; filterContext.Result = result; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 403; } else { filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.Forbidden, "You do not have permission to access this operation"); } break; case 404: if (!AjaxReq) { ViewResult result = new ViewResult { ViewName = "Page_404", //错误页 MasterName = null, //指定母版页 ViewData = null, //指定模型 TempData = filterContext.Controller.TempData //临时数据 }; filterContext.Result = result; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 404; } else { filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.NotFound, "The requested resource was not found"); } break; case 500: if (!AjaxReq) { ViewResult result = new ViewResult { ViewName = "Page_500", //错误页 MasterName = null, //指定母版页 ViewData = null, //指定模型 TempData = filterContext.Controller.TempData }; filterContext.Result = result; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 500; } else { filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.InternalServerError, filterContext.Exception.Message); } break; default: if (!AjaxReq) { ViewResult result = new ViewResult { ViewName = "Page_500", //错误页 MasterName = null, //指定母版页 ViewData = null, //指定模型 TempData = filterContext.Controller.TempData }; filterContext.Result = result; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 500; } else { filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.InternalServerError, filterContext.Exception.Message); } break; } //设置异常已经处理,否则会被其他异常过滤器覆盖 filterContext.ExceptionHandled = true; //在派生类中重写时,获取或设置一个值,该值指定是否禁用IIS自定义错误。 filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; }
最后在MVC项目根目录下 App_Start文件的FilterConfig.CS文件下 修改内容
完毕 现在你控制器所有异常 都会被捕获