zoukankan      html  css  js  c++  java
  • MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器

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

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

    如图:

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

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

     View Code

    GlobalFilters.cs

     View Code

    再看看,App_Start里面的FilterConfig.cs

     View Code

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

     View Code

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


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

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

     View Code

    Global.asax的Application_start中

     View Code

    最后App_Start中的MyFilterConfig.cs

     View Code

    OK!

  • 相关阅读:
    [BZOJ2296] [POJ Challenge] 随机种子
    [BZOJ1026] [SCOI2009] windy数 (数位dp)
    [BZOJ1306] [CQOI2009] match循环赛 (搜索)
    [BZOJ2654] tree (kruskal & 二分答案)
    [BZOJ3506] [Cqoi2014] 排序机械臂 (splay)
    [BZOJ1552] [Cerc2007] robotic sort (splay)
    [BZOJ3110] [Zjoi2013] K大数查询 (树套树)
    BZOJ3611: [Heoi2014]大工程
    BZOJ2286: [Sdoi2011]消耗战
    BZOJ3876: [Ahoi2014]支线剧情
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4351159.html
Copyright © 2011-2022 走看看