目录html
对上节的内容进行了补充web
MVC有四种过滤器:Authorization、Exception、Action、Result,咱们要用的的就是Exception异常过滤器mvc
当咱们新建一个MVC项目后,异常过滤器就已经自动在程序中注册了,先从上一节所说的全局配置文件开始,Global.asax这个文件中的Application_Start方法会在程序启动时运行,其中的即默认注册了全局过滤器,如图app
咱们能够进入RegisterGlobalFilters方法查看,这个方法中默认注册了一个异常处理过滤器,也就是说默认状态的MVC程序发生异常时会被程序捕获处理,处理方式是跳转至错误页面,也就是上一篇文章说的Layout文件夹下面的Error页ide
但使用异常过滤器有一个大前提是要在Web.config中打开自定义错误处理的设置,customErrors节点要设置为“On”,这一设置默认是关闭的,也就是说要手动加上才行debug
<system.web> <compilation debug="true" targetFramework="4.6.1"/> <httpRuntime targetFramework="4.6.1"/> <customErrors mode="On"> </customErrors> </system.web>
须要注意的是 404 错误,这种类型的异常并不会被过滤器捕获3d
可是能够在web.config中添加节点进行自定义配置,跳转到相应的页面日志
<customErrors mode="On"> <error redirect="~/Error/NotFound" statusCode="404" /> </customErrors>
public class ErrorController : Controller { // GET: Error public ActionResult Index() { return View(); } public ActionResult CustomHttpError() { ViewBag.Message = "有错误"; //HandleErrorInfo //ExceptionContext return View(); } public ActionResult NotFound() { return View(); } }
MVC默认的异常过滤器能够知足基本的须要,可是若是要对一些异常进行特殊处理就须要咱们自定义过滤器的内容,能够经过重写OnException方法达到这个目的code
public class CustomHandleErrorAttribute : HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { /* 调用基类的OnException方法,实现基础的功能。 * 若是要彻底的自定义,就不须要调用基类的方法 */ base.OnException(filterContext); /* 此处可进行记录错误日志,发送错误通知等操做 * 经过Exception对象和HttpException对象可获取相关异常信息。 * Exception exception = filterContext.Exception; * HttpException httpException = new HttpException(null, exception); */ } }
示例代码orm
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; } }