ASP.NET MVC 中的过滤器

这里用实例说明各种过滤器的用法,有不对的地方还请大神指出,共同探讨。

1. ActionFilter 方法过滤器:

  接口名为 IActionFilter ,在控制器方法调用前/后执行。

在新建的MVC程序中,添加一个类 MyFilter1Attribute 并继承ActionFilterAttribute抽象类

从上图可以看到 ActionFilterAttribute 中的所有方法,且有相应的介绍,我们可以通过继承 ActionFilterAttribute 类,并重写(override)它的方法,从而实现自定义Filter

   public class MyFilter1Attribute: ActionFilterAttribute
    {
        /// <summary>
        /// 该方法会在Action方法执行之前调用
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Write("我是OnActionExecuting,我在Ation方法调用前执行<br/>");
            base.OnActionExecuting(filterContext);
        }


        /// <summary>
        /// 该方法会在Action方法执行之后调用
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write("我是OnActionExecuted,我在Action方法调用后执行<br/>");
            base.OnActionExecuted(filterContext);
        }

    }

然后创建一个HomeController控制器,并添加FilterTest的测试Action

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        [MyFilter1]
        public void FilterTest()
        {
            Response.Write("我是Action方法,我在这里执行了.....<br/>");
        }
    }

运行程序并访问FilterTest方法:

 上图可看出它的一个执行顺序

 但是有时候也有可能有这样的场景:当检查到Action有标识某个Attribute的时候,我们需要跳出,并不执行后续的方法的情况,我们可以通过filterContextActionDescriptior类中的IsDefained方法进行判断检查

 

     /// <summary>
        /// 该方法会在Action方法执行之前调用
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Write("我是OnActionExecuting,我在Ation方法调用前执行<br/>");
            //判断Action方法时是否有贴上MyFilter1Attribute标签
            if (filterContext.ActionDescriptor.IsDefined(typeof(MyFilter1Attribute), false))
            {
                //如果有,为该Action方法直接返回ContentResult,则该Action方法在这里就有了返回值,相当于在这里就结束了,不会再去执行之后的方法,例如:OnActionExecuted
                filterContext.Result = new ContentResult();
            }
            base.OnActionExecuting(filterContext);
        }

 

2.ResultFilter 结果过滤器:

  接口名为 IResultFilter,在控制器方法调用完,跳转至View页面前/后调用

 同样在 MyFilter1Attribute 类中重写 OnResultExecuting 方法和  OnResultExecuted 方法

        /// <summary>
        /// 该方法在Action方法返回结果之前执行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Write("我是OnResultExecuting,我在Action方法返回结果前执行<br/>");
            base.OnResultExecuting(filterContext);
        }

        /// <summary>
        /// 该方法在Action方法返回结果之后执行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write("我是OnResultExecuted,我在Action方法返回结果后执行<br/>");
            base.OnResultExecuted(filterContext);
        }
View Code

然后在HomeController控制器中添加 FilterTest1

        [MyFilter1]
        public ActionResult FilterTest1()
        {
            Response.Write("我是测试Action1方法,我在这里执行了.....<br/>");
            return View();
        } 
View Code

运行程序,并访问 FilterTest1 ,执行结果如下:

可以看出OnResultExecuting 方法是在返回结果页面之前执行的,而OnResultExecuted是返回结果页面之后执行的

 

3.ExceptionFilter 异常操作过滤器:

  接口名为 IExceptionFilter,在控制器的Action方法抛出异常时执行

 可以通过异常过滤器捕获Controller中发生的异常,并记录到日志。

添加MyExceptionAttribute类,并继承HandleErrorAttribute,如下

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnException(ExceptionContext filterContext)
        {
            filterContext.HttpContext.Response.Write("我是OnException,在Controller中发生异常时进入<br/>");

            //获取到异常对象
            Exception ex = filterContext.Exception;
            //获取请求的Controller和Action
            string controllerName = filterContext.RouteData.Values["controller"].ToString();
            string actionName = filterContext.RouteData.Values["action"].ToString();
            //记录日志
            string errMessage = string.Format("异常消息:控制器为:{0},Action为:{1},异常信息为:{2};", controllerName, actionName, ex.Message);
            OutPutLog(errMessage);

            //标记异常已做处理
            filterContext.ExceptionHandled = true;
            base.OnException(filterContext);
        }

        /// <summary>
        /// 输出日志
        /// </summary>
        /// <param name="message"></param>
        public void OutPutLog(string message)
        {
            string path = AppDomain.CurrentDomain.BaseDirectory + "/Logs.txt";
            using (StreamWriter sw = new StreamWriter(path, true, Encoding.Default))
            {
                sw.Flush();
                sw.WriteLine("时间:" + DateTime.Now);
                sw.WriteLine("内容:" + message);
                sw.WriteLine("---------------------------------------------");
            }
        }
View Code

HomeController中添加FilterTest3

 [MyException]
 public ActionResult FilterTest3()
 {
     Response.Write("我是测试Action3方法,我在这里执行了.....<br/>");
     string str = "131464ddddd";
     int i = int.Parse(str);
     return View();
 }

运行程序并访问 FilterTest3方法,将会在 str 转换成int类型时抛出异常,随后将进入OnException方法,并记录日志如下:

4.AuthorizationFilter 授权过滤器:

  接口名为 IauthorizationFilter,在所有过滤器中最先执行

添加一个MyFilter2Attribute类,并继承AuthorizeAttribute类,然后重写其OnAuthorization方法:

    public class MyFilter2Attribute: AuthorizeAttribute
    {

        /// <summary>
        /// 在所有的Action方法过滤之前执行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            filterContext.HttpContext.Response.Write("我是OnAuthorization,在所有Action方法过滤器之前执行<br/>");//base.OnAuthorization(filterContext);
        }
    }

HoneController控制器中添加 FilterTest2

    [MyFilter1]
    [MyFilter2]
    public ActionResult FilterTest2()
    {
        Response.Write("我是测试Action2方法,我在这里执行了.....<br/>");
        return View();
    }

运行程序并访问 FilterTest2  结果如下:

从上图执行结果可以看出,OnAuthorization 权重是最高的,将会在其他所有过滤器之前执行。

 

 

 

注意:

  ActionFilter 和 ResultFilter 不仅可以对单个方法进行操作,也能对整个Controller进行操作,将过滤的头部属性移至控制名称上面即可。

 

posted @ 2019-08-23 15:36  Andy·Hu  阅读(1165)  评论(1编辑  收藏  举报