实现MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器
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过滤器的更多相关文章
- MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器
实现MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器 MVC开发中几种以AOP方式实现的Filters是非常好用的,默认情况下,我们通过A ...
- Asp.Net 5使用Area及自定义Area
Asp.Net Mvc里有一个叫做Area的技术,就是可以把不同逻辑组件的controller, view等放到不同的文件夹里.比如所有管理相关的都放到Admin area里.其实之前我一直对这个功能 ...
- ASP.NET MVC和ASP.NET Core MVC中获取当前URL/Controller/Action (转载)
ASP.NET MVC 一.获取URL(ASP.NET通用): [1]获取完整url(协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [ ...
- vue中自定义指令vue.direvtive,自定义过滤器vue.filter(),vue过渡transition
自定义指令 默认设置的核心指令( v-model,v-bind,v-for,v-if,v-on等 ),Vue 也允许注册自定义指令.注意,在 Vue2.0 里面,代码复用的主要形式和抽象是组件——然而 ...
- Django框架(七)—— 模板层:变量、过滤器、标签、自定义标签和过滤器
目录 模板层:变量.过滤器.标签.自定义标签和过滤器 一.模板层变量 1.语法 2.使用 二.模板层之过滤器 1.语法 2.常用过滤器 3.其他过滤器 三.模板值标签 1.for标签 2.if标签 3 ...
- Spring MVC 项目搭建 -6- spring security 使用自定义Filter实现验证扩展资源验证,使用数据库进行配置
Spring MVC 项目搭建 -6- spring security使用自定义Filter实现验证扩展url验证,使用数据库进行配置 实现的主要流程 1.创建一个Filter 继承 Abstract ...
- Spring MVC 项目搭建 -4- spring security-添加自定义登录页面
Spring MVC 项目搭建 -4- spring security-添加自定义登录页面 修改配置文件 <!--spring-sample-security.xml--> <!-- ...
- MVC自定义路由01-为什么需要自定义路由
本篇体验自定义路由以及了解为什么需要自定义路由. 准备 □ View Models using System.Collections.Generic; namespace MvcApplicati ...
- asp.net mvc maproute定义可变数量的自定义片断变量
有时候我们定义了如{controller}/{action}/{id}之类的路由规则,但是后面还可能跟上一堆可能会有可能不会有,但是路由规则是一样的,如{controller}/{action}/{i ...
随机推荐
- SQL Server相关书籍
SQL Server相关书籍 (排名不分先后) Microsoft SQL Server 企业级平台管理实践 SQL Server 2008数据库技术内幕 SQL Server性能调优实战 SQL S ...
- OEL上使用yum install oracle-validated 简化主机配置工作
环境:OEL 5.7 + Oracle 10.2.0.5 RAC 如果你正在用OEL(Oracle Enterprise Linux)系统部署Oracle,那么可以使用yum安装oracle-vali ...
- ZKWeb网页框架1.2正式发布
发行日志 https://github.com/zkweb-framework/ZKWeb/blob/master/ReleaseNotes/ReleaseNote.1.2.md 主要改动 更新 ZK ...
- 程序猿都没对象,JS竟然有对象?
现在做项目基本是套用框架,不论是网上的前端还是后端框架,也会寻找一些封装好的插件拿来即用,但还是希望拿来时最好自己过后再回过头了解里面的原理,学习里面优秀的东西,不论代码封装性,还是小到命名. 好吧, ...
- 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)
建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...
- 【微信小程序开发•系列文章六】生命周期和路由
这篇文章理论的知识比较多一些,都是个人观点,描述有失妥当的地方希望读者指出. [微信小程序开发•系列文章一]入门 [微信小程序开发•系列文章二]视图层 [微信小程序开发•系列文章三]数据层 [微信小程 ...
- 使用JavaScript为一张图片设置备选路径
在做网页开发的时候,有时候希望给图片设置一个备选路径,即,当src属性对应的主路径加载失败的时候,图片可以马上切换到备选路径.这样,即使主路径失效了,显示备用路径也不会影响网页的正常体验. 注意到网页 ...
- 让你从零开始学会写爬虫的5个教程(Python)
写爬虫总是非常吸引IT学习者,毕竟光听起来就很酷炫极客,我也知道很多人学完基础知识之后,第一个项目开发就是自己写一个爬虫玩玩. 其实懂了之后,写个爬虫脚本是很简单的,但是对于新手来说却并不是那么容易. ...
- C#中一些常用的加密和哈希处理
URL编码,默认UTF8编码方式 /// <summary> /// URL编码,默认UTF8编码方式 /// </summary> /// <param name=&q ...
- 在 Linux 中使用 Eclipse 和 Gnu Autotools 管理 C/C++ 项目
在我该系列的之前的所有随笔中,都是采用 Linux 发行版自带的包管理工具(如 apt-get.yum 等)进行软件的安装和卸载,从来没有向大家展示使用源代码自行编译安装软件的方法.但是长期混迹于 U ...