实现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!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。