MVC统一异常处理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rxjhfmf/article/details/51187744

关于MVC过滤器的介绍,网上的文章很多,可以看一下这个:《MVC过滤器详解》

在使用之前,先梳理一下过滤器的执行顺序:

一般的过滤器执行顺序

  1. IAuthorizationFilter->OnAuthorization(授权)
  2. IActionFilter ->OnActionExecuting(行为)
  3. Action
  4. IActionFilter ->OnActionExecuted(行为)
  5. IResultFilter ->OnResultExecuting(结果)
  6. View
  7. IResultFilter ->OnResultExecuted(结果)
  8. *IExceptionFilter ->OnException(异常),此方法并不在以上的顺序执行中,有异常发生时即会执行,有点类似于中断

当同时在Controller和Action中都设置了过滤器后,执行顺序一般是由外到里,即“全局”->“控制器”->“行为”

  1. Controller->IAuthorizationFilter->OnAuthorization
  2. Action ->IAuthorizationFilter->OnAuthorization
  3. Controller->IActionFilter ->OnActionExecuting
  4. Action ->IActionFilter ->OnActionExecuting
  5. Action
  6. Action ->IActionFilter ->OnActionExecuted
  7. Controller->IActionFilter ->OnActionExecuted
  8. Controller->IResultFilter ->OnResultExecuting
  9. Action ->IResultFilter ->OnActionExecuting
  10. Action ->IResultFilter ->OnActionExecuted
  11. Controller->IResultFilter ->OnActionExecuted

因为异常是从里往外抛,因次异常的处理顺序则刚好相反,一般是由里到外,即“行为”->“控制器”->“全局”

  1. Action ->IExceptionFilter->OnException
  2. Controller->IExceptionFilter->OnException

所以,为了精简代码量,只要在程序启动时注册全局过滤器就OK了;

过滤器代码如下:

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
    public class LogExceptionAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled)
            {
                string controllerName = (string)filterContext.RouteData.Values["controller"];
                string actionName = (string)filterContext.RouteData.Values["action"];
                string msgTemplate = "在执行 controller[{0}] 的 action[{1}] 时产生异常";
                Exception ex = filterContext.Exception;

                //doing some log
            }

            if (filterContext.Result is JsonResult)
            {
                //当结果为json时,设置异常已处理
                filterContext.ExceptionHandled = true;
            }
            else
            {
                //否则调用原始设置
                base.OnException(filterContext);
            }
        }
    }

LogExceptionAttribute继承了HandleErrorAttribute,重写的OnException方法在记录异常日志后,通过调用base.OnException回到了系统默认的异常处理上,实现了向错误页面的跳转。
代码中增加了对JsonResult的判断,可以在此基础上进行条件的扩充,对一些特殊的情况进行处理。

注册全局过滤器代码:

public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new LogExceptionAttribute());
            //filters.Add(new HandleErrorAttribute());
        }
    }

这种处理模式是还是比较通用的。在没有特定需求的情况下,控制器,逻辑层,数据访问层等,都不需要增加额外的异常处理的代码,产生异常后直接外抛,最终都会被异常过滤器拦截并进行处理,特别适合于站点上线后的运维;
当然,如果在开发时,使用try catch 会比较直接,但是会严重导致代码的臃肿!!!

这里只是举了一个过滤器的使用案例,我们可以举一反三,使用过滤器做更多的事情,比如说权限控制、站点操作日志记录等,后续再补充权限控制的内容

展开阅读全文

没有更多推荐了,返回首页