实现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 ...
随机推荐
- 03.SQLServer性能优化之---存储优化系列
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 概 述:http://www.cnblogs.com/dunitian/p/60413 ...
- node-webkit 环境搭建与基础demo
首先去github上面下载(地址),具体更具自己的系统,我的是windows,这里只给出windows的做法 下载windows x64版本 下载之后解压,得到以下东西 为了方便,我们直接在这个目录中 ...
- Sublime Text3安装JsHint
介绍 Sublime Text3使用jshint依赖Nodejs,SublimeLinter和Sublimelinter-jshint. NodeJs的安装省略. 安装SublimeLinter Su ...
- 微软.NET Core RC2正式发布,横跨所有平台
.NET官方博客宣布了<Announcing .NET Core RC2 and .NET Core SDK Preview 1>,正式如期发布了.NET Core RC2, 现在可以放心 ...
- Key/Value之王Memcached初探:二、Memcached在.Net中的基本操作
一.Memcached ClientLib For .Net 首先,不得不说,许多语言都实现了连接Memcached的客户端,其中以Perl.PHP为主. 仅仅memcached网站上列出的语言就有: ...
- Jquery 搭配 css 使用,简单有效
前几篇博客中讲了Jquery的基础和点击实际,下面来说一下和css搭配着来怎么做 还是和往常一样,举个例子 好几个方块,然后设置颜色 <!DOCTYPE html PUBLIC "-/ ...
- jQuery之Deferred源码剖析
一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...
- EC笔记:第4部分:20、传递引用代替传值
考虑以下场景: #include <iostream> #include <string> using namespace std; struct Person { strin ...
- 浏览器的兼容模式下的button中文字垂直方向不居中显示
<button style="cursor:pointer;vertical-align: middle;" >删除</button> 这时候垂直不居中. ...
- JAVA环境变量和TomCat服务器配置
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选.对于一个初学者来说,可以这样 ...