MVC深度分析(一)扩展MVC内置过滤器(一)

2014-11-24 00:45:05 · 作者: · 浏览: 2

最近在公司项目中用MVC内置的权限过滤器实现权限控制功能,查阅以前的代码发现权限过滤接口已经被实现在其他地方,作用是用户访问系统任何页面时都要判断是否登录,如果没有登录,就会自动读取本机的域账号信息,并自动完成登录动作。现在遇到的问题是,如果新加的权限验证功能基于权限过滤器,就必须考虑过滤器的执行先后顺序,由于权限验证基于用户信息,所以我要保证用户自动登录的过滤器在权限过滤器之前被执行,但是MVC的权限过滤器默认是优先级最高的,我又不想让非权限验证的功能丢在权限过滤器中执行,又想要这个过滤器执行优先级一定高于权限过滤器,怎么办呢?看来只有通过扩展MVC内置过滤器的方式实现了。

一、初步计划
  自定义一个过滤器接口IFirstFilter,它会在MVC框架中被最先调用,程序员只需要创建实现该接口的特性,就可以实现自定义过滤器。

二、实现步骤
   1) 重写ControllerActionInvoker的方法InvokeAction

  由于MVC框架的action方法调用统一通过InvokeAction执行,在这个方法中会调用MVC内置过滤器,我们通过重写它来给自定义过滤器“内置”进去。另外还自定义两个方法,GetFirstFilters方法用来通过反射特性获取自定义的特性,InvokeFirstFilters用来执行自定义的过滤器。

  新建类文件UserControllerActionInvoker.cs,代码如下:

view sourceprint 01 using System;

02 using System.Collections.Generic;

03 using System.Linq;

04 using System.Web;

05 using System.Web.Mvc;

06 using System.Reflection;

07

08 namespace MvcUserFilter.MVC

09 {

10 public class UserControllerActionInvoker : ControllerActionInvoker

11 {

12 public override bool InvokeAction(ControllerContext controllerContext, string actionName)

13 {

14 if (controllerContext != null && !string.IsNullOrEmpty(actionName))

15 {

16 ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);

17 ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);

18

19 if (actionDescriptor != null)

20 {

21 IList firstFilters = GetFirstFilters(actionDescriptor);

22 FirstFilterContext firstContext = InvokeFirstFilters(controllerContext, firstFilters, actionDescriptor);

23 if (firstContext.Result != null)

24 {

25 InvokeActionResult(controllerContext, firstContext.Result);

26 return true;

27 }

28 }

29 }

30

31 return base.InvokeAction(controllerContext, actionName);

32

33 }

34

35 private IList GetFirstFilters(ActionDescriptor actionDescriptor)

36 {

37

38 MethodInfo methodInfo = (actionDescriptor as ReflectedActionDescriptor).MethodInfo;

39

40 FilterAttribute[] typeFilters = (FilterAttribute[])methodInfo.ReflectedType.GetCustomAttributes(typeof(FilterAttribute), true /* inherit */);

41 FilterAttribute[] methodFilters = (FilterAttribute[])methodInfo.GetCustomAttributes(typeof(FilterAttribute), true /* inherit */);

42 List orderedFilters = typeFilters.Concat(methodFilters).OrderBy(attr => attr.Order).ToList();

43

44 IList firstFilters = new List();

45

46 foreach (FilterAttribute filter in orderedFilters)

47 {

48 IFirstFilter castFilter = filter as IFirstFilter;

49 if (castFilter != null)

50 {

51 firstFilters.Add(castFilter);

52 }

53 }

54 return firstFilters;

55 }

56

57 private FirstFilterContext InvokeFirstFilters(Contr