• 实现MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器


    MVC开发中几种以AOP方式实现的Filters是非常好用的,默认情况下,我们通过App_Start中的FilterConfig来实现的过滤器注册是全局的,也就是整个应用程序都会使用的,针对单独的Filter我们不得不去单独的Controller或者Action去定义

    如图:

    那么问题来了,我现在想在FitlerConfig里面去维护所有的过滤器,但是又想实现自定义的过滤器该咋搞,MVC默认不支持!

    我们先来看看,MVC默认的Fitlers注册是怎样的
    官方源码:GlobalFilterCollection.cs

     1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
     2 
     3 using System.Collections;
     4 using System.Collections.Generic;
     5 using System.Linq;
     6 using System.Web.Mvc.Filters;
     7 using System.Web.Mvc.Properties;
     8 
     9 namespace System.Web.Mvc
    10 {
    11     public sealed class GlobalFilterCollection : IEnumerable<Filter>, IFilterProvider
    12     {
    13         private List<Filter> _filters = new List<Filter>();
    14 
    15         public int Count
    16         {
    17             get { return _filters.Count; }
    18         }
    19 
    20         public void Add(object filter)
    21         {
    22             AddInternal(filter, order: null);
    23         }
    24 
    25         public void Add(object filter, int order)
    26         {
    27             AddInternal(filter, order);
    28         }
    29 
    30         private void AddInternal(object filter, int? order)
    31         {
    32             ValidateFilterInstance(filter);
    33             _filters.Add(new Filter(filter, FilterScope.Global, order));
    34         }
    35 
    36         public void Clear()
    37         {
    38             _filters.Clear();
    39         }
    40 
    41         public bool Contains(object filter)
    42         {
    43             return _filters.Any(f => f.Instance == filter);
    44         }
    45 
    46         public IEnumerator<Filter> GetEnumerator()
    47         {
    48             return _filters.GetEnumerator();
    49         }
    50 
    51         IEnumerator IEnumerable.GetEnumerator()
    52         {
    53             return _filters.GetEnumerator();
    54         }
    55 
    56         IEnumerable<Filter> IFilterProvider.GetFilters(ControllerContext controllerContext,
    57             ActionDescriptor actionDescriptor)
    58         {
    59             return this;
    60         }
    61 
    62         public void Remove(object filter)
    63         {
    64             _filters.RemoveAll(f => f.Instance == filter);
    65         }
    66 
    67         private static void ValidateFilterInstance(object instance)
    68         {
    69             if (instance != null && !(
    70                 instance is IActionFilter ||
    71                 instance is IAuthorizationFilter ||
    72                 instance is IExceptionFilter ||
    73                 instance is IResultFilter ||
    74                 instance is IAuthenticationFilter))
    75             {
    76                 throw Error.InvalidOperation(MvcResources.GlobalFilterCollection_UnsupportedFilterInstance,
    77                     typeof(IAuthorizationFilter).FullName,
    78                     typeof(IActionFilter).FullName,
    79                     typeof(IResultFilter).FullName,
    80                     typeof(IExceptionFilter).FullName,
    81                     typeof(IAuthenticationFilter).FullName);
    82             }
    83         }
    84     }
    85 }
    View Code

    GlobalFilters.cs

     1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
     2 
     3 namespace System.Web.Mvc
     4 {
     5     public static class GlobalFilters
     6     {
     7         static GlobalFilters()
     8         {
     9             Filters = new GlobalFilterCollection();
    10         }
    11 
    12         public static GlobalFilterCollection Filters { get; private set; }
    13     }
    14 }
    View Code

    再看看,App_Start里面的FilterConfig.cs

    1 public class FilterConfig
    2     {
    3         public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    4         {
    5             filters.Add(new HandleErrorAttribute());
    6         }
    7     }
    View Code

    可以发现,其实是GlobalFilters里面定义了静态的GlobalFIlterCollection对象,然后通过FilterConfig像这个静态的集合注册Filters,那么我们没看到MVC哪调用了这个集合,是的,Global里面是没有明确写出来,但是我们来看看FilterProviders.cs的源码

     1 namespace System.Web.Mvc
     2 {
     3     public static class FilterProviders
     4     {
     5         static FilterProviders()
     6         {
     7             Providers = new FilterProviderCollection();
     8             Providers.Add(GlobalFilters.Filters);
     9             Providers.Add(new FilterAttributeFilterProvider());
    10             Providers.Add(new ControllerInstanceFilterProvider());
    11         }
    12 
    13         public static FilterProviderCollection Providers { get; private set; }
    14     }
    15 }
    View Code

    在静态的构造函数中就已经通过Providers.Add(GlobalFilters.Filters);把GlobalFilters.Filters集合给添加进去了,然后MVC每次请求会调用IFilterProvider.GetFilters,那为什么自带的GlobalFilterCollection就不能实现自定义的过滤器呢,请看最上面GlobalFilterCollection.cs的GetFilters代码,他直接返回所有的Filters,而且这个类不能重写,好吧!我们来自己写一个实现自定义过滤器!
    可以完全照搬GlobalFilterCollection.cs,GlobalFilters.cs代码,然后根据自己的需求改改
    这里我们要通过GetFilters实现自己的筛选规则
    看看原始方法源码:

    IEnumerable<Filter> IFilterProvider.GetFilters(ControllerContext controllerContext,
                ActionDescriptor actionDescriptor)
            {
                return this;
            }
    

    这个方法传进来两个参数:ControllerContext和ActionDescriptor
    我们添加Add方法

    /// <summary>
            /// 注册注册局部规则过滤器
            /// </summary>
            /// <param name="func"></param>
            /// <param name="filter"></param>
            /// <param name="order"></param>
            public void Add(Func<ControllerContext, ActionDescriptor, bool> func, object filter, int order)
            {
                Add(func, filter, order);
            }
    
    
            private void Add(Func<ControllerContext, ActionDescriptor, bool> func, object filter, int? order)
            {
                ValidateFilterInstance(filter);
                items.Add(new FilterItem
                {
                    filter = new Filter(filter, FilterScope.Global, order),
                    func = func
                });
            }
    
    FilterItem是我自己写的一个类,用来存储设置的Filters跟规则的Func
    public class FilterItem
        {
            public Filter filter { get; set; }
            public Func<ControllerContext, ActionDescriptor, bool> func { get; set; }
        }
    

    然后改造GetFilters方法

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
            {
                foreach (FilterItem item in items)
                {
                    if (item.func == null)
                    {
                        yield return item.filter;
                    }
                    else
                    {
                        bool result = item.func(controllerContext, actionDescriptor);
                        if (result)
                            yield return item.filter;
                    }
                }
            }
    

    这样在执行GetFilters的时候就会根据注册的所有Filters进行筛选匹配出符合条件的Filters
    最后App_Start中自定义FilterConfig注册Filtes
    然后在Global添加自定义的Filters注册
    FilterProviders.Providers.Add(Geo.Mvc.Provider.GlobalFilters.Filters);

    测试:

    新建HomeController,写上两个Action分别为Index和Test

    public ActionResult Index()
            {
                return Content("Index");
            }
    
            public ActionResult Test()
            {
                return Content("test");
            }
    

    自己随便写个Filter测试

    public class TestFilter : IActionFilter
        {
    
            public void OnActionExecuted(ActionExecutedContext filterContext)
            {
                filterContext.HttpContext.Response.Write("执行前!<br/>");
            }
    
            public void OnActionExecuting(ActionExecutingContext filterContext)
            {
                filterContext.HttpContext.Response.Write("执行后!<br/>");
            }
        }
    

    去App_Start中自定义的Filter注册

    public class MyFilterConfig
        {
            public static void RegistGlobalFilters(Geo.Mvc.Provider.MyFlterCollection filters)
            {
                //filters.Add(new Filters.TestFilter());
                filters.Add((c, a) =>
                {
                    return string.Compare(a.ActionName, "test", true) == 0;
                }, new Filters.TestFilter());
            }
        }
    

    最后执行Index跟Test方法
    结果如下:


    这个就是当初我们所希望实现的效果!

    不知道怎么放附件,我直接贴我的代码好了!

      1 public static class GlobalFilters
      2     {
      3         static GlobalFilters()
      4         {
      5             Filters = new MyFlterCollection();
      6         }
      7 
      8         public static MyFlterCollection Filters { get; private set; }
      9     }
     10 
     11     public class MyFlterCollection : IEnumerable<Filter>, IFilterProvider
     12     {
     13         List<FilterItem> items = new List<FilterItem>();
     14         /// <summary>
     15         /// Filter数量
     16         /// </summary>
     17         public int Count
     18         {
     19             get
     20             {
     21                 return items.Count;
     22             }
     23         }
     24         /// <summary>
     25         /// 注册全局过滤器
     26         /// </summary>
     27         /// <param name="filter"></param>
     28         public void Add(object filter)
     29         {
     30             Add(null, filter, null);
     31         }
     32         /// <summary>
     33         /// 注册全局过滤器
     34         /// </summary>
     35         /// <param name="filter"></param>
     36         /// <param name="order"></param>
     37         public void Add(object filter, int order)
     38         {
     39             Add(null, filter, order);
     40         }
     41         /// <summary>
     42         /// 注册注册局部规则过滤器
     43         /// </summary>
     44         /// <param name="func"></param>
     45         /// <param name="filter"></param>
     46         public void Add(Func<ControllerContext, ActionDescriptor, bool> func, object filter)
     47         {
     48             Add(func, filter, null);
     49         }
     50         /// <summary>
     51         /// 注册注册局部规则过滤器
     52         /// </summary>
     53         /// <param name="func"></param>
     54         /// <param name="filter"></param>
     55         /// <param name="order"></param>
     56         public void Add(Func<ControllerContext, ActionDescriptor, bool> func, object filter, int order)
     57         {
     58             Add(func, filter, order);
     59         }
     60 
     61 
     62         private void Add(Func<ControllerContext, ActionDescriptor, bool> func, object filter, int? order)
     63         {
     64             if(ValidateFilterInstance(filter))
     65             items.Add(new FilterItem
     66             {
     67                 filter = new Filter(filter, FilterScope.Global, order),
     68                 func = func
     69             });
     70         }
     71         /// <summary>
     72         /// 获取过滤器
     73         /// </summary>
     74         /// <param name="controllerContext"></param>
     75         /// <param name="actionDescriptor"></param>
     76         /// <returns></returns>
     77         public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
     78         {
     79             foreach (FilterItem item in items)
     80             {
     81                 if (item.func == null)
     82                 {
     83                     yield return item.filter;
     84                 }
     85                 else
     86                 {
     87                     bool result = item.func(controllerContext, actionDescriptor);
     88                     if (result)
     89                         yield return item.filter;
     90                 }
     91             }
     92         }
     93 
     94         public IEnumerator<Filter> GetEnumerator()
     95         {
     96             return this.GetEnumerator();
     97         }
     98 
     99         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    100         {
    101             return this.GetEnumerator();
    102         }
    103 
    104         /// <summary>
    105         /// 清除所有过滤器
    106         /// </summary>
    107         public void Clear()
    108         {
    109             items.Clear();
    110         }
    111         /// <summary>
    112         /// 是否包含过滤器
    113         /// </summary>
    114         /// <param name="filter"></param>
    115         /// <returns></returns>
    116         public bool Contains(object filter)
    117         {
    118             return items.Any(t => t.filter.Instance == filter);
    119         }
    120         /// <summary>
    121         /// 删除过滤器
    122         /// </summary>
    123         /// <param name="filter"></param>
    124         public void Remove(object filter)
    125         {
    126             items.RemoveAll(t => t.filter.Instance == filter);
    127         }
    128 
    129         /// <summary>
    130         /// 验证过滤器是否为IActionFilter,IAuthorizationFilter,IExceptionFilter,IResultFilter
    131         /// </summary>
    132         /// <param name="instance"></param>
    133         /// <returns></returns>
    134         private static bool ValidateFilterInstance(object instance)
    135         {
    136             if (instance == null) return false;
    137             return
    138                 instance is IActionFilter ||
    139                 instance is IAuthorizationFilter ||
    140                 instance is IExceptionFilter ||
    141                 instance is IResultFilter;
    142         }
    143     }
    144     /// <summary>
    145     /// 存储
    146     /// </summary>
    147     public class FilterItem
    148     {
    149         public Filter filter { get; set; }
    150         public Func<ControllerContext, ActionDescriptor, bool> func { get; set; }
    151     }
    View Code

    Global.asax的Application_start中

    1 //FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    2             MyFilterConfig.RegistGlobalFilters(Geo.Mvc.Provider.GlobalFilters.Filters);
    3             FilterProviders.Providers.Add(Geo.Mvc.Provider.GlobalFilters.Filters);
    View Code

    最后App_Start中的MyFilterConfig.cs

     1 public class MyFilterConfig
     2     {
     3         public static void RegistGlobalFilters(Geo.Mvc.Provider.MyFlterCollection filters)
     4         {
     5             //filters.Add(new Filters.TestFilter());
     6             filters.Add((c, a) =>
     7             {
     8                 return string.Compare(a.ActionName, "test", true) == 0;
     9             }, new Filters.TestFilter());
    10         }
    11     }
    View Code

    OK!

  • 相关阅读:
    自定义、操作cookie
    云中沙箱学习笔记2-ECS之初体验
    云中沙箱学习笔记1-快速部署并使用MySQL数据库
    练习小程序
    理解Thread.sleep()函数
    排序:冒泡排序;直接选择排序;反转排序
    float和double
    BigDecimal
    Linux学习笔记5(2)-CentOS7中Tomcat8修改jvm内存配置
    ret2dl学习笔记
  • 原文地址:https://www.cnblogs.com/263613093/p/4349908.html
Copyright © 2020-2023  润新知