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

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

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

如图:

MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器_第1张图片

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

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

  View Code

GlobalFilters.cs

  View Code

再看看,App_Start里面的FilterConfig.cs

  View Code

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

  View Code

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

1
2
3
4
5
IEnumerable<Filter> IFilterProvider.GetFilters(ControllerContext controllerContext,
             ActionDescriptor actionDescriptor)
         {
             return  this ;
         }

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <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
             });
         }
1
FilterItem是我自己写的一个类,用来存储设置的Filters跟规则的Func
1
2
3
4
5
public  class  FilterItem
     {
         public  Filter filter {  get set ; }
         public  Func<ControllerContext, ActionDescriptor,  bool > func {  get set ; }
     }

然后改造GetFilters方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

1
2
3
4
5
6
7
8
9
public  ActionResult Index()
         {
             return  Content( "Index" );
         }
 
         public  ActionResult Test()
         {
             return  Content( "test" );
         }

自己随便写个Filter测试

1
2
3
4
5
6
7
8
9
10
11
12
13
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注册

1
2
3
4
5
6
7
8
9
10
11
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方法
结果如下:
MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器_第2张图片

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

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

  View Code

Global.asax的Application_start中

  View Code

最后App_Start中的MyFilterConfig.cs

  View Code

OK!

你可能感兴趣的:(controller)