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

如图:

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

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

 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

 using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc.Filters;
using System.Web.Mvc.Properties; namespace System.Web.Mvc
{
public sealed class GlobalFilterCollection : IEnumerable<Filter>, IFilterProvider
{
private List<Filter> _filters = new List<Filter>(); public int Count
{
get { return _filters.Count; }
} public void Add(object filter)
{
AddInternal(filter, order: null);
} public void Add(object filter, int order)
{
AddInternal(filter, order);
} private void AddInternal(object filter, int? order)
{
ValidateFilterInstance(filter);
_filters.Add(new Filter(filter, FilterScope.Global, order));
} public void Clear()
{
_filters.Clear();
} public bool Contains(object filter)
{
return _filters.Any(f => f.Instance == filter);
} public IEnumerator<Filter> GetEnumerator()
{
return _filters.GetEnumerator();
} IEnumerator IEnumerable.GetEnumerator()
{
return _filters.GetEnumerator();
} IEnumerable<Filter> IFilterProvider.GetFilters(ControllerContext controllerContext,
ActionDescriptor actionDescriptor)
{
return this;
} public void Remove(object filter)
{
_filters.RemoveAll(f => f.Instance == filter);
} private static void ValidateFilterInstance(object instance)
{
if (instance != null && !(
instance is IActionFilter ||
instance is IAuthorizationFilter ||
instance is IExceptionFilter ||
instance is IResultFilter ||
instance is IAuthenticationFilter))
{
throw Error.InvalidOperation(MvcResources.GlobalFilterCollection_UnsupportedFilterInstance,
typeof(IAuthorizationFilter).FullName,
typeof(IActionFilter).FullName,
typeof(IResultFilter).FullName,
typeof(IExceptionFilter).FullName,
typeof(IAuthenticationFilter).FullName);
}
}
}
}

GlobalFilters.cs

 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

 namespace System.Web.Mvc
{
public static class GlobalFilters
{
static GlobalFilters()
{
Filters = new GlobalFilterCollection();
} public static GlobalFilterCollection Filters { get; private set; }
}
}

再看看,App_Start里面的FilterConfig.cs

 public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}

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

 namespace System.Web.Mvc
{
public static class FilterProviders
{
static FilterProviders()
{
Providers = new FilterProviderCollection();
Providers.Add(GlobalFilters.Filters);
Providers.Add(new FilterAttributeFilterProvider());
Providers.Add(new ControllerInstanceFilterProvider());
} public static FilterProviderCollection Providers { get; private set; }
}
}

在静态的构造函数中就已经通过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方法
结果如下:

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

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

 public static class GlobalFilters
{
static GlobalFilters()
{
Filters = new MyFlterCollection();
} public static MyFlterCollection Filters { get; private set; }
} public class MyFlterCollection : IEnumerable<Filter>, IFilterProvider
{
List<FilterItem> items = new List<FilterItem>();
/// <summary>
/// Filter数量
/// </summary>
public int Count
{
get
{
return items.Count;
}
}
/// <summary>
/// 注册全局过滤器
/// </summary>
/// <param name="filter"></param>
public void Add(object filter)
{
Add(null, filter, null);
}
/// <summary>
/// 注册全局过滤器
/// </summary>
/// <param name="filter"></param>
/// <param name="order"></param>
public void Add(object filter, int order)
{
Add(null, filter, order);
}
/// <summary>
/// 注册注册局部规则过滤器
/// </summary>
/// <param name="func"></param>
/// <param name="filter"></param>
public void Add(Func<ControllerContext, ActionDescriptor, bool> func, object filter)
{
Add(func, filter, null);
}
/// <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)
{
if(ValidateFilterInstance(filter))
items.Add(new FilterItem
{
filter = new Filter(filter, FilterScope.Global, order),
func = func
});
}
/// <summary>
/// 获取过滤器
/// </summary>
/// <param name="controllerContext"></param>
/// <param name="actionDescriptor"></param>
/// <returns></returns>
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;
}
}
} public IEnumerator<Filter> GetEnumerator()
{
return this.GetEnumerator();
} System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
} /// <summary>
/// 清除所有过滤器
/// </summary>
public void Clear()
{
items.Clear();
}
/// <summary>
/// 是否包含过滤器
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
public bool Contains(object filter)
{
return items.Any(t => t.filter.Instance == filter);
}
/// <summary>
/// 删除过滤器
/// </summary>
/// <param name="filter"></param>
public void Remove(object filter)
{
items.RemoveAll(t => t.filter.Instance == filter);
} /// <summary>
/// 验证过滤器是否为IActionFilter,IAuthorizationFilter,IExceptionFilter,IResultFilter
/// </summary>
/// <param name="instance"></param>
/// <returns></returns>
private static bool ValidateFilterInstance(object instance)
{
if (instance == null) return false;
return
instance is IActionFilter ||
instance is IAuthorizationFilter ||
instance is IExceptionFilter ||
instance is IResultFilter;
}
}
/// <summary>
/// 存储
/// </summary>
public class FilterItem
{
public Filter filter { get; set; }
public Func<ControllerContext, ActionDescriptor, bool> func { get; set; }
}

Global.asax的Application_start中

 //FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
MyFilterConfig.RegistGlobalFilters(Geo.Mvc.Provider.GlobalFilters.Filters);
FilterProviders.Providers.Add(Geo.Mvc.Provider.GlobalFilters.Filters);

最后App_Start中的MyFilterConfig.cs

 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) == ;
}, new Filters.TestFilter());
}
}

OK!

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

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

    实现MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器 MVC开发中几种以AOP方式实现的Filters是非常好用的,默认情况下,我们通过A ...

  2. Asp.Net 5使用Area及自定义Area

    Asp.Net Mvc里有一个叫做Area的技术,就是可以把不同逻辑组件的controller, view等放到不同的文件夹里.比如所有管理相关的都放到Admin area里.其实之前我一直对这个功能 ...

  3. ASP.NET MVC和ASP.NET Core MVC中获取当前URL/Controller/Action (转载)

    ASP.NET MVC 一.获取URL(ASP.NET通用): [1]获取完整url(协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [ ...

  4. vue中自定义指令vue.direvtive,自定义过滤器vue.filter(),vue过渡transition

    自定义指令 默认设置的核心指令( v-model,v-bind,v-for,v-if,v-on等 ),Vue 也允许注册自定义指令.注意,在 Vue2.0 里面,代码复用的主要形式和抽象是组件——然而 ...

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

    目录 模板层:变量.过滤器.标签.自定义标签和过滤器 一.模板层变量 1.语法 2.使用 二.模板层之过滤器 1.语法 2.常用过滤器 3.其他过滤器 三.模板值标签 1.for标签 2.if标签 3 ...

  6. Spring MVC 项目搭建 -6- spring security 使用自定义Filter实现验证扩展资源验证,使用数据库进行配置

    Spring MVC 项目搭建 -6- spring security使用自定义Filter实现验证扩展url验证,使用数据库进行配置 实现的主要流程 1.创建一个Filter 继承 Abstract ...

  7. Spring MVC 项目搭建 -4- spring security-添加自定义登录页面

    Spring MVC 项目搭建 -4- spring security-添加自定义登录页面 修改配置文件 <!--spring-sample-security.xml--> <!-- ...

  8. MVC自定义路由01-为什么需要自定义路由

    本篇体验自定义路由以及了解为什么需要自定义路由. 准备 □ View Models using System.Collections.Generic;   namespace MvcApplicati ...

  9. asp.net mvc maproute定义可变数量的自定义片断变量

    有时候我们定义了如{controller}/{action}/{id}之类的路由规则,但是后面还可能跟上一堆可能会有可能不会有,但是路由规则是一样的,如{controller}/{action}/{i ...

随机推荐

  1. 【.net 深呼吸】序列化中的“引用保留”

    假设 K 类中有两个属性/字段的类型相同,并且它们引用的是同一个对象实例,在序列化的默认处理中,会为每个引用单独生成数据. 看看下面两个类. [DataContract] public class 帅 ...

  2. 说说Golang的使用心得

    13年上半年接触了Golang,对Golang十分喜爱.现在是2015年,离春节还有几天,从开始学习到现在的一年半时间里,前前后后也用Golang写了些代码,其中包括业余时间的,也有产品项目中的.一直 ...

  3. Atitit 项目语言的选择 java c#.net  php??

    Atitit 项目语言的选择 java c#.net  php?? 1.1. 编程语言与技术,应该使用开放式的目前流行的语言趋势1 1.2. 从个人职业生涯考虑,java优先1 1.3. 从项目实际来 ...

  4. 基于SignalR实现B/S系统对windows服务运行状态的监测

    通常来讲一个BS项目肯定不止单独的一个BS应用,可能涉及到很多后台服务来支持BS的运行,特别是针对耗时较长的某些任务来说,Windows服务肯定是必不可少的,我们还需要利用B/S与windows服务进 ...

  5. Entity Framework 教程——DBContext

    DBContext: 在之前的章节<创建实体数据模型>中,EDM为我们创建了SchoolDBEntities 类,它派生子System.Data.Entity.DbContext这个类,这 ...

  6. 每天一个设计模式-7 生成器模式(Builder)

    每天一个设计模式-7 生成器模式(Builder) 一.实际问题 在讨论工厂方法模式的时候,提到了一个导出数据的应用框架,但是并没有涉及到导出数据的具体实现,这次通过生成器模式来简单实现导出成文本,X ...

  7. 让你从零开始学会写爬虫的5个教程(Python)

    写爬虫总是非常吸引IT学习者,毕竟光听起来就很酷炫极客,我也知道很多人学完基础知识之后,第一个项目开发就是自己写一个爬虫玩玩. 其实懂了之后,写个爬虫脚本是很简单的,但是对于新手来说却并不是那么容易. ...

  8. MMORPG大型游戏设计与开发(攻击区域 扇形)

    距离上次发布已经有了很长一段时间,期间由于各种原因没有更新这方面的技术分享,在这里深表遗憾.在MMO或其他的游戏中,会有针对各种形状的计算,通常在攻击区域里不会很复杂,常见的为矩形.圆形.扇形.今天分 ...

  9. 从贝叶斯到粒子滤波——Round 1

    粒子滤波确实是一个挺复杂的东西,从接触粒子滤波到现在半个多月,博主哦勒哇看了N多篇文章,查略了嗨多资料,很多内容都是看了又看,细细斟酌.今日,便在这里验证一下自己的修炼成果,请各位英雄好汉多多指教. ...

  10. Windows更新清理工具 (winsxs 清理工具)

    Windows 更新清理工具是一款效果非常显著的Windows7.Windows8操作系统清理优化工具!经常安装系统的朋友相比有所体会,刚刚安装完成的Win7.Win8其实占的空间并不大,去掉页面文件 ...