• mvc源码解读(13)MVC四大过滤器之ResultFilter


        上一篇讲到ActionFilter,这一篇我们来讲解ResultFilter,顾名思义,就是结果过滤器。和ActionFilter要实现抽象类ActionFilterAttribute里面的四个方法一样,我们自定义的ResultFilter的过滤特性类也要继承ActionFilterAttribute才行,同时实现接口IResultFilter里面的方法:

      public interface IResultFilter {
            void OnResultExecuting(ResultExecutingContext filterContext);
            void OnResultExecuted(ResultExecutedContext filterContext);
        }

    OnResultExecuting是在动作结果执行之前执行,OnResultExecuted是在动作结果之后执行,什么是动作结果?我们可以这样来理解,Action就是一个动作,这个动作的结果是可能会返回一个ViewResult渲染到浏览器中,在整个Action的生命周期之内成为Action的执行,之前执行OnActionExecuting,之后执行OnResultExecuted方法,那OnActionExecuted方法和OnResultExecuting方法在什么时候执行呢,答案是在Action之后,Result之前。我们来看一个的demo吧:

         我们定义一个MyTestResultFiter,让他继承自ActionFilterAttribute类,具体实现如下:

    public class MyTestResultFiter : ActionFilterAttribute     {

            public override void OnActionExecuting(ActionExecutingContext filterContext)

                {

                        filterContext.HttpContext.Response.Write("OnActionExecuting方法:<br/>");        

                        base.OnActionExecuted(filterContext);            

                }        

             public override void OnActionExecuted(ActionExecutedContext filterContext) 

                {            

                         filterContext.HttpContext.Response.Write("OnActionExecuted方法<br/>");            

                        base.OnActionExecuted(filterContext);        

                }        

               public override void OnResultExecuting(ResultExecutingContext filterContext)        

               {            

                        filterContext.HttpContext.Response.Write("OnResultExecuting方法: <br/>");            

                       base.OnResultExecuting(filterContext);        

              }        

            public override void OnResultExecuted(ResultExecutedContext filterContext)        

             {            

                    filterContext.HttpContext.Response.Write("OnResultExecuted方法:<br/>");            

                    base.OnResultExecuted(filterContext);        

              }

        同时我们创建一个MVC的项目,创建一个MyResultFilter控制器,具体如下:

    public class MyResultFilterController : Controller
        {
            [MyTestResultFiter]
            public ActionResult Index()
            {
                Response.Write("这里执行是Action方法,非ViewResult<br/>");
                return View();
            }
        }

    Index的视图如下:

    @{     Layout = null; }

    <!DOCTYPE html>

    <html> <head>  <title>Index</title> </head>

    <body><div>        

    <p>ViewResult:这里是Result的首页哦~~~~~~</p>    

    </div> </body> </html>

    运行结果如下:

        OnActionExecuting方法和OnResultExecuted方法的执行顺序无可争议,问题在于Action里面Response.Write的内容是先于OnActionExecuted方法执行的,因此我们可以断定:OnActionExecuted方法的执行时间实在Action的生命周期之后执行的,Action的生命周期说白了就是大括号{}里面的代码,OnResultExecuting方法实在动作结果之前执行,我们的示例中动作结果输出的是Index这个视图,因此会看到OnResultExecuted实在ViewResult之后执行。上图中示例执行顺序OnActionExecuting>Action>OnActionExecuted>OnResultExecuting>ViewResult>OnResultExecuted。

        但是如果只有动作结果过滤器来过滤请求的话,标签要在每一个动作上做上标签,显然是不符合软件的设计思想的,mvc好在为我们提供了一个全局的过滤器,全局过滤器我们需要在全局文件Global.asax中进行注册,我们按照刚才的例子稍加改进一下,来看具体的结果。

        在Global.asax中注册全局过滤器:

     public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
                filters.Add(new MyTestResultFiter() { FilterMessage="标志全局过滤器"});
            }

     同时将MyTestResultFiter过滤器稍作修改如下:

     [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]    

    public class MyTestResultFiter : ActionFilterAttribute {

            public string FilterMessage { get; set; }

            public override void OnActionExecuting(ActionExecutingContext filterContext)         {            

                     filterContext.HttpContext.Response.Write("OnActionExecuting方法:" + FilterMessage + "<br/>");            

                     base.OnActionExecuting(filterContext);        

             }        

           public override void OnActionExecuted(ActionExecutedContext filterContext)         {            

                    filterContext.HttpContext.Response.Write("OnActionExecuted方法" + FilterMessage + "<br/>");            

                    base.OnActionExecuted(filterContext);        

           }        

         public override void OnResultExecuting(ResultExecutingContext filterContext)         {            

                     filterContext.HttpContext.Response.Write("OnResultExecuting方法" + FilterMessage + "<br/>");            

                     base.OnResultExecuting(filterContext);        

          }        

          public override void OnResultExecuted(ResultExecutedContext filterContext)         {            

                    filterContext.HttpContext.Response.Write("OnResultExecuted方法" + FilterMessage + "<br/>");            

                   base.OnResultExecuted(filterContext);        

         }    

    }

    同时注意将MyTestResultFiter标注为AllowMultiple = true,这样MyTestResultFiter就可以执行在Controller和Action上都起作用。否则执行执行Action上的MyTestResultFiter特性。运行结果如下:

    但是还有一点我们需要注意的是Controller它本身也是一个过滤器,我们来看Controller的定义:

    public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter

     Controller也实现了mvc的四大过滤器的接口,因此我们来测试一下这个Controller过滤器的执行顺序是什么?我们在MyResultFilter里面稍作修改:

     [MyTestResultFiter(FilterMessage="这里是Controller的:")]
        public class MyResultFilterController : Controller
        {
            [MyTestResultFiter(FilterMessage = "这里是Action的:")]
            public ActionResult Index()
            {
                Response.Write("这里执行是Action方法,非ViewResult<br/>");
                return View();
            }
        }

     最终执行的效果如下:

    因此整个过滤器的执行顺序大致如下:全局过滤器>Controller上标记的特性过滤器>Action上标记的特性过滤器,里面的四种方法的执行顺序大家看完之后应该明白了吧~~~

  • 相关阅读:
    http强转https websocket
    apache http添加证书转成https
    insert into
    分割字符串和截取字符串:split 和substring
    java实现http请求
    Oracle 中 decode 函数用法
    LeetCode:154. 寻找旋转排序数组中的最小值 II
    LeetCode:153. 寻找旋转排序数组中的最小值
    LeetCode:151. 翻转字符串里的单词
    LeetCode:145. 二叉树的后序遍历
  • 原文地址:https://www.cnblogs.com/ghhlyy/p/2934808.html
Copyright © 2020-2023  润新知