实现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. bash构造tmux显示tmux ssh状态

    要求: 于tmux内部链接ssh什么时候, 假设有多个ssh主机. 我们要显示相应的主机ip要显示筛查 实现效果 编辑你的bashrc, 由于我习惯在root下操作, 所以/root/.bashrc. ...

  2. VirtualBox创建虚拟电脑、执行Genymotion模拟器报错

    当安装完Genynition关于Android应用的调试模拟器之后,在Genymotion执行的平台virtualBox:VirtualBox创建虚拟电脑.执行Genymotion模拟器报错: 错误卖 ...

  3. 玩转Web之JavaScript(一)-----javaScript语法总结(一) 与鼠标操作有关的语法

    click()  对象.click()  使对象被点击. event.clientX  返回最后一次点击鼠标 X 坐标值: event.clientY  返回最后一次点击鼠标 Y 坐标值: event ...

  4. 在高德地图应用api,和api展出的标记小的应用程序

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  5. C# 中使用WebClient 请求 https

    WebClient 请求 启用SSL的站点 时,如果站点的证书是不可信的,请求会被阻止,解决办法如下: 添加以下代码: ServicePointManager.ServerCertificateVal ...

  6. 第七章——DMVs和DMFs(3)——用DMV和DMF监控TempDB

    原文:第七章--DMVs和DMFs(3)--用DMV和DMF监控TempDB 前言: 我们都知道TempDB是SQLServer的系统数据库,且SQLServer的日常运作严重依赖这个库.因此,监控T ...

  7. 在SQL Server Management Studio中可以运行作业但是用T-SQL运行则失败

    原文:在SQL Server Management Studio中可以运行作业但是用T-SQL运行则失败 问题: 在SQL Server Management Studio中可以运行作业但是用T-SQ ...

  8. 【Java】实现一个根据日期判断星座程序的编写

    思路 直接根据月份做索引,然后根据日期边界判断是本月的星座还是上月的. 算法 private static String getAstro(int month, int day) { String[] ...

  9. JUnit实战(2) - JUnit核心(使用Suite来组合测试)

    创建Java Project项目:ch02-internals MasterTestSuite.java package com.manning.junitbook.ch02.internals; i ...

  10. USACO maze1 BFS

    不写了很长的时间bfs该,很长一段时间的中间失误,当延期一次延伸成功的新节点的节点应该被标记为参观.否则,在某些情况下无限期延长队列. 输入一个小坑爹处理称号,能够进来当字符串被读取.然后用周围的墙上 ...