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

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

如图:

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

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

 

GlobalFilters.cs

再看看,App_Start里面的FilterConfig.cs

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

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

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

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

Global.asax的Application_start中

最后App_Start中的MyFilterConfig.cs

OK!

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

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

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

  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. MVC自定义路由01-为什么需要自定义路由

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

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

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

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

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

随机推荐

  1. mac平台adb、tcpdump捕手android移动网络数据包

    在移动电话的发展app当我们希望自己的下才能看到app网络发出请求,这个时候我们需要tcpdump工具包捕获.实现tcpdump空灵,以下步骤需要: 在这里,在android 华为手机 P6对于样本 ...

  2. jquery经常使用事件(整理)

    Jquery事件 (一).事件列表. 1.blur() 当失去焦点时触发.包含鼠标点击离开和TAB键离开. 2.change() 当元素获取焦点后,值改变失去焦点事触发. 3.click() 当鼠标单 ...

  3. 前框 (一个)zTree 从数据库树形菜单动态加载

    这些天做动态菜单使用此插件.现在有一个非常广泛的开源框架,最新QUI框架是菜单部分使用这个插件开发,因此,它是非常值获取深入的研究和探讨,通过使用非常丰富的感觉功能,己开发和编写,官网上有非常详尽的A ...

  4. oracle record is locked by another user

    这个问题的根源先说说:午后更改数据库表,保存更改后,却没有提交完整.突然,去什么地方调试,拔掉网线,然后插上网线,这个出现record is locked by another user错误.网上找原 ...

  5. 6-06. 理性任务调度(25)(拓扑排序啊 ZJU_PAT)

    主题链接:http://pat.zju.edu.cn/contests/ds/6-06 假定一个project项目由一组子任务构成,子任务之间有的能够并行运行.有的必须在完毕了其他一些子任务后才干运行 ...

  6. 【SSH2(理论+实践)】--Hibernate步步(一个)

    前几个博客讨论SSH2该框架Struts,它代表层,集成封装.和使用WebWork作为核心处理,依赖映射是它的处理核心.在使用时需要Struts.xml配置相应Action和Interceptor够完 ...

  7. php用魔术方法__call实现类函数重载

    因为php是弱类型语言,不喜欢c++通过改变函数返回相同的值键入的参数的数目和功能将过载!但在需求函数的实际发展可能过载.开发需求,我们能够通过魔术方法__call()来实现函数重载. class T ...

  8. Windows下一个MySQL有些错误的解决方法

    1.无论是什么提示.我们有一个直接看错误日志.由于它描述了最具体描述错误日志. 于MySQL安装文件夹中找到 my.ini简介 看日志保存路径 2. 我的错误是[ERROR] Fatal error: ...

  9. 深入浅出学习Hibernate框架(一):从实例入手初识Hibernate框架

    这篇博客是hibernate学习的第一篇,主要简介hibernate框架,之后简单说一下hibernate的文件夹结构,最后写一个简单的hibernate实例.通过这三步来简单的认识一下hiberna ...

  10. java 中类的加载顺序(转)

    1.虚拟机在首次加载Java类时,会对静态初始化块.静态成员变量.静态方法进行一次初始化 2.只有在调用new方法时才会创建类的实例 3.类实例创建过程:按照父子继承关系进行初始化,首先执行父类的初始 ...