利用GlobalFilterProvider创建自定义全局过滤器

如需转载请注明出处。
 

在MVC3中有一个新的GlobalFilter全局过滤器注册功能。

在MVC3的Global.ascx文件中,有一个RegisterGlobalFilters方法,把需要全局应用的Filter在这里注册,所有的Action就都会有注册的这些Filter。GlobalFilter解决了以前一个Filter要在每一个需要的Action上重复添加的繁琐,但是现在,当一个Filter只有个别Action不需要使用时,难道要重新回到以前多次添加的状况?

——GlobalFilterProvider用于创建自定义的全局过滤器,使过滤器可以在Global.cs中全局注册,但只应用于满足自定义条件的ControllerAction

 

在Web.config中配置全局过滤器

 

考虑到灵活性,我们在Web.config里配置我们需要应用的各个Filter以及应用情况。配置结构如下:

<!--自定义全局过滤器-->
<GlobalFilter>
<Allfilters>
<filter name="GlobalFilterTest.FilterProvider.ActionLogFilterAttribute" assembly="GlobalFilterTest">
<except controller="Account" action="LogOn"/>
<except controller="Home" action="*"/>
</filter>
</Allfilters>
</GlobalFilter>

其中:

<filter></filter>节点用于配置一个过滤器

name为需要全局注册的Filter类的类名(格式为 命名空间.类名)

assembly为该Filter类的程序集名称

<except/>节点用于设置该过滤器不需要应用的Controller和Action,如果该Filter需要全局注册,不需要配置该节点;否则,需要按情况依次配置不需要应用的Controller和Action。其中 * 表示该Controller或者Action中所有的情况。

例子中的配置表示,ActionLogFilterAttribute需要全局注册,但名为AccountController下的名为LogOn的Action需要添加,名为Home的Controller下的所有Action都需要添加。 

 

定义节点接口及实现类

定义好配置文件节点之后,我们便需要考虑解析配置文件的逻辑。在此之前,我们先要定义节点接口及实现类。

 1     ///<summary>
2 /// 用于提供代表配置文件中全局过滤器节点的接口
3 ///</summary>
4 interface IFilterNode
5 {
6 string Name { get; set; }
7 string Assembly { get; set; }
8 List<Except> Excepts { get; set; }
9 }
10
11 ///<summary>
12 /// 配置文件中全局过滤器节点类
13 ///</summary>
14 public class FilterNode : IFilterNode
15 {
16 public string Name
17 {
18 get;
19 set;
20 }
21
22 public string Assembly
23 {
24 get;
25 set;
26 }
27
28 public List<Except> Excepts
29 {
30 get;
31 set;
32 }
33 }
34
35 ///<summary>
36 /// 用于提供配置文件中过滤器非全局应用情况的接口
37 ///</summary>
38 interface IExcept
39 {
40 string Controller { get; set; }
41 string Action { get; set; }
42 }
43
44 ///<summary>
45 /// 配置文件中过滤器非全局应用情况节点类
46 ///</summary>
47 public class Except : IExcept
48 {
49 public string Controller
50 {
51 get;
52 set;
53 }
54
55 public string Action
56 {
57 get;
58 set;
59 }
60 }

 

读取配置文件 

定义好节点类之后,我们来解析配置文件,实际上就是读取XML文档。

 1     ///<summary>
2 /// 过滤器配置文件读取接口
3 ///</summary>
4 public interface IFilterConfiguration
5 {
6 List<FilterNode> GetAlltheFilter();
7 }
8
9 ///<summary>
10 /// 过滤器配置文件读取类
11 ///</summary>
12 public class FilterConfiguration : IFilterConfiguration
13 {
14 ///<summary>
15 /// 读取过滤器配置
16 ///</summary>
17 public List<FilterNode> GetAlltheFilter()
18 {
19 string configpath = Utils.GetMapPath(ConfigurationManager.AppSettings["WebRegistrationPath"]);
20 XDocument config = XDocument.Load(configpath);
21 List<FilterNode> FilterList = new List<FilterNode>();
22
23 var filter = from per in config.Descendants("filter")
24 let items = from i in per.Elements("except")
25 select new
26 {
27 Controller = i.Attribute("controller").Value,
28 Action = i.Attribute("action").Value
29 }
30 select new
31 {
32 name = per.Attribute("name").Value,
33 assembly = per.Attribute("assembly").Value,
34 items = items
35 };
36
37 foreach (var per in filter)
38 {
39 FilterNode thefilter = new FilterNode { Excepts = new List<Except>() };
40 thefilter.Name = per.name;
41 thefilter.Assembly = per.assembly;
42 foreach (var i in per.items)
43 {
44 thefilter.Excepts.Add(new Except { Controller = i.Controller, Action = i.Action });
45 }
46 FilterList.Add(thefilter);
47 }
48
49 return FilterList;
50 }

 

实例化Filter 

 

经过之前我们就得到了一个Filters列表,列表的每一项都是一个Filter,并包含它的应用情况等信息,下面来对Filter进行实例化,此处是重点。

 1     ///<summary>
2 /// 过滤器实例化类
3 ///</summary>
4 public class ActionFilterProvider : IFilterProvider
5 {
6 public string AssemblyString;
7 public string NameString;
8 private IList<ControllerAction> actions = new List<ControllerAction>();
9
10 ///<summary>
11 /// 过滤器应用范围设置
12 ///<param name="controllername"></param>
13 ///<param name="actionname"></param>
14 ///</summary>
15 public void Add(string controllername, string actionname)
16 {
17 actions.Add(new ControllerAction() { ControllerName = controllername, ActionName = actionname });
18 }
19
20 public IEnumerable<System.Web.Mvc.Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
21 {
22 bool need = true;
23 foreach (ControllerAction action in actions)
24 {
25 if ((action.ControllerName == actionDescriptor.ControllerDescriptor.ControllerName || action.ControllerName == "*")
26 && (action.ActionName == actionDescriptor.ActionName || action.ActionName == "*"))
27 {
28 need = false;
29 break;
30 }
31 }
32
33 if (need)
34 {
35 yield return new System.Web.Mvc.Filter((FilterAttribute)Assembly.Load(AssemblyString).CreateInstance(NameString), FilterScope.First, null);
36 }
37 yield break;
38 }
39 }
40
41 internal class ControllerAction
42 {
43 internal string ControllerName { get; set; }
44 internal string ActionName { get; set; }
45 }

在这里注意我们继承了IFilterProvider的接口,这是微软提供的自定义ActionFilter的接口,我们要实现它的GetFilters方法。该方法根据条件返回一个IEnumerable<Filter>对象。

 

注册全局过滤器  

最后我们提供一个用于注册这些Filter的类。

 1     ///<summary>
2 /// 全局过滤器注册类
3 ///</summary>
4 public class GlobalFilterProvider
5 {
6 FilterConfiguration filterconfig = new FilterConfiguration();
7
8 ///<summary>
9 /// 注册全局过滤器
10 ///<param name="filters"></param>
11 public void RegisterFilters(GlobalFilterCollection filters)
12 {
13 foreach (var perfilter in filterconfig.GetAlltheFilter())
14 {
15 ActionFilterProvider provider = new ActionFilterProvider();
16
17 provider.AssemblyString = perfilter.Assembly;
18 provider.NameString = perfilter.Name;
19 foreach (var peritem in perfilter.Excepts)
20 {
21 provider.Add(peritem.Controller, peritem.Action);
22 }
23 FilterProviders.Providers.Add(provider);
24 }
25 }
26
27 }

 
然后在Global.cs文件中注册。

 1     public class MvcApplication : System.Web.HttpApplication
2 {
3 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
4 {
5 filters.Add(new HandleErrorAttribute());
6 GlobalFilterProvider provider = new GlobalFilterProvider();
7 provider.RegisterFilters(filters);
8 }
9
10 public static void RegisterRoutes(RouteCollection routes)
11 {
12 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
13
14 routes.MapRoute(
15 "Default", // 路由名称
16 "{controller}/{action}/{id}", // 带有参数的 URL
17 new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
18 );
19 }
20
21 protected void Application_Start()
22 {
23 AreaRegistration.RegisterAllAreas();
24
25 RegisterGlobalFilters(GlobalFilters.Filters);
26 RegisterRoutes(RouteTable.Routes);
27 }
28 }

 

 

 

 

posted @ 2011-10-24 14:41  hyven  阅读(1268)  评论(4编辑  收藏  举报