实现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 { getset; }
        public Func<ControllerContext, ActionDescriptor, bool> func { getset; }
    }

然后改造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. 【Android基础】eclipse常用快捷键

    Alt+/ 内容辅助键--列出相关内容 Ctrl+shift+o 导入所需的所有类包 Ctrl+1 对现有错误的n中解决方案 Crtl+d 删除所在行或者全部 CTRL+alt+上下键 上下复制 Cr ...

  2. struts 1.x 原理

    Struts 当我接触到这个框架的时候.我就在想为什么是struts,而不是什么CraigFramework.结构.支撑,这样来理解也不难怪了. 为什么须要struts? 在struts in act ...

  3. VS2015 C#6.0

    VS2015 C#6.0 中的那些新特性 VS2015在自己机器上确实是装好了,(全部安装的话,在Java SE 开发工具包 会卡顿很长时间,我直接关闭,然后重启电脑,重新修复安装搞定), 想来体验一 ...

  4. RH133读书 笔记(3) - Lab 3 Configuring the kernel

    Lab 3 Configuring the kernel Goal: Develop skills tuning the /proc filesystem. Gain some experience ...

  5. 避免内存重叠memmove()性能

    #include <iostream> #include <string.h> using namespace std; void* memmove(void *dst, co ...

  6. 如何设置eclipse在默认模式下打开文件

    如何设置eclipse在默认模式下打开文件 打开eclipse.选择例如以下:windows --> preferences --> General --> Editors --&g ...

  7. 国外流行的共享网站实现:facebook,twitter,google+1,tumblr等待

    近期需要做相关的国外几个站点共享,本来我以为它会和weibo.在同样的烦恼空间,什么appkey啦,apptoken啦.api啦.结果非常意外的发现并非如此恼火. Twitter分享: https:/ ...

  8. SQL Server审计功能入门:CDC(Change Data Capture)

    原文:SQL Server审计功能入门:CDC(Change Data Capture) 介绍 SQL Server 2008引入了CDC(Change Data Capture),它能记录: 1. ...

  9. SWTBOK实践测试系列(2) --您将提交测试开发者版本号打回来了?

    开发商斗争非常多晚,提交测试的最终版本. 它们可以缓和.但噩耗传来很快,软件没有通过预测试测试团队(为了确保在测试过程,开发者提交的代码验证的基本功能或业务流程).开发王经理.快速找到负责预测试试验张 ...

  10. NSIS:安装、卸载时检查程序是否正在运行

    原文 NSIS:安装.卸载时检查程序是否正在运行 如果我们要安装或升级的程序正在运行,文件肯定会替换不成功,以下代码可以提示用户结束正在运行的程序. 需要使用插件FindProcDLL.dll,下载路 ...