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

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 }

再看看,App_Start里面的FilterConfig.cs

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

可以发现,其实是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 }

在静态的构造函数中就已经通过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     }

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);

最后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     }

OK!

时间: 2024-10-08 23:59:23

实现MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器的相关文章

Django(七)—— 模板层:变量、过滤器、标签、自定义标签和过滤器

模板层:变量.过滤器.标签.自定义标签和过滤器 将页面的设计和Python的代码分离开会更干净简洁更容易维护. 我们可以使用 Django的 模板系统 (Template System)来实现这种模式 # django模板修改的视图函数 def current_time(req): from django.template import Template,Context now=datetime.datetime.now() t=Template('<html><body>现在时刻

制作自定义背景Button按钮、自定义形状Button的全攻略(转)

在Android开发应用中,默认的Button是由系统渲染和管理大小的.而我们看到的成功的移动应用,都是有着酷炫的外观和使用体验的.因此,我们在开发产品的时候,需要对默认按钮进行美化.在本篇里,笔者结合在应用开发中的经验,探讨一下自定义背景的按钮.自定义形状按钮的实现方法. 首先看实现效果截图: 自定义背景的按钮目前有2种方式实现,矢量和位图. 1. 矢量图形绘制的方式 矢量图形绘制的方式实现简单,适合对于按钮形状和图案要求不高的场合.步骤如下: (a) 使用xml定义一个圆角矩形,外围轮廓线实

自定义View 篇一--------《自定义View流程分析》

本文部分内容参考自掘金网:点击打开链接 坐标图解: 概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会比较多.但是任何复杂的技术后面都是一点点简单知识的积累.通过对自定义控件的学习去可以更深入的掌握android的相关知识点,所以学习android自定义控件是很有必要的.所以,今天写的是怎么去自定义一个控件.而不是里面涉及到的细化知识点.一个东西我

FineUIMvc随笔(4)自定义回发参数与自定义回发

声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 不能忘却的回发 在上一篇文章中,我们对FineUIMvc中的回发进行了详细描述,目的是为了告诉大家: 1. FineUIMvc中的回发其实是请求控制器方法的另一种表述而已 2. 回发是轻量级,只会传入你允许传入的参数 3. 回发是AJAX过程 4. 可以通过控件ID来快捷的附加相关参数 但是,上一篇文章没有讲解如何在回发中自行附加需要的参数,这个参数来源可以是: 1. 静态字符串 2. JavaScript变量或者函数返回值

超酷的计步器APP——炫酷功能实现,自定义水波纹特效、自定义炫酷开始按钮、属性动画的综合体验

超酷的计步器APP--炫酷功能实现,自定义水波纹特效.自定义炫酷开始按钮.属性动画的综合体验 好久没写博客了,没给大家分享技术了,真是有些惭愧.这段时间我在找工作,今年Android的行情也不怎么好,再加上我又是一个应届生,所以呢,更是不好找了.但是我没有放弃,经过自己的不懈努力,还是找到了自己喜欢的Android工作,心里的一块石头终于落下了.但是迎接我来的是更多的挑战,我喜欢那种不断的挑战自我,在困难中让自己变得更强大的感觉.相信阳光总在风雨后,因为每一个你不满意的现在,都有一个你没有努力的

自定义View(一),初识自定义View

看了无数资料,总结一下自定义View 先明白一个自定义View的三大流程 onMeasure() 测量,决定View的大小 onLayout() 布局,决定View在ViewGroup中的位置 onDraw() 绘制,画出这个View的内容 这三个方法都存在于View类中,我们自定义View需要针对这三个方法做出修改来达到我们需要的目标或功能 先来一个最基本的例子,我们单纯的画一个圆,我们只需修改onDraw()方法即可 MyCustomVew.java public class MyCusto

常规功能和模块自定义系统 (cfcmms)—015模块自定义概述(2权限)

常规功能和模块自定义系统 (cfcmms)-015模块自定义概述(2权限) 模块的权限的自定义也是这个系统的重要部分.在本系统中现在模块的权限有三大类:模块操作权限.记录可视范围限定.附加操作权限. 模块操作权限:可以对模块进行浏览.新增.修改.删除.审核.审批等的设置.可以通过生成和隐藏相应的按钮来具体控制权限的设置.如某人无删除权限,则在该模块的操作界面上没有删除按钮.对于一般的管理系统而言这些功能基本上是够用了. 记录可视范围限定:可以在任意模块加上可视范围的限定.在某个父模块上加上可视范

常规功能和模块自定义系统(cfcmms)—004可自定义的项目

常规功能和模块自定义系统(cfcmms)-004可自定义的项目 可以在前台浏览器里可进行的配置项目如下图: 版权声明:本文为博主原创文章,未经博主允许不得转载.

VS自定义项目模板:[8]自定义模板参数

如何在模板中定义和使用自定义模板参数? 1 CustomParameters元素的父元素是TemplateContent 下面定义一个模板参数$Para1$,值为MyObj. ps:CustomParameters元素定义在Project上方时,编译器会有一个警告,但不影响模板项目生成. 2 将源文件Class1.cs文件生成为目标项目的MyObj.cs文件 修改模板文件中的TargetFileName,模板项目文件中的包含文件以及Class1.cs的类名为自定义模板参数$Para1$ 3 重新