2009-07-06 56 views
8

我正在尝试编写一个单元测试,它将遍历我的控制器类中的所有操作方法,以查找没有某些与安全相关的属性的操作方法(例如[Authorize])。ASP.NET MVC如何知道一个方法是一个动作方法?

ASP.NET路由引擎如何确定哪些方法是动作方法?显然,操作方法必须是公开的,但像ToString()这样的方法不是操作方法,所以这里有一些逻辑。

回答

1

我不再是懒惰,我找到了答案,其中大部分是System.Web.Mvc.ActionMethodSelector.PopulateLookupTables()(感谢反射!)

private IEnumerable<MethodInfo> GetActionMethods(Type controllerType) 
    { 
     return Array.FindAll(controllerType.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance), IsValidActionMethod); 
    } 

    private static bool IsValidActionMethod(MethodInfo methodInfo) 
    { 
     return (!methodInfo.IsSpecialName && !methodInfo.GetBaseDefinition().DeclaringType.IsAssignableFrom(typeof(Controller)) && 
      !methodInfo.GetCustomAttributes(typeof(NonActionAttribute), true).Any()); 
    } 

我很惊讶地看到所有的我的基础控制器类上的公共方法暴露在他们身上没有任何安全性!

8

控制器中的所有方法都被视为操作,但非公共方法除外。

首先,方法通过名称进行匹配:MethodName = ActionName。

如果要覆盖默认行为,请使用[ActionName]属性。

public MyController 
{ 
    [ActionName("ActionY")] 
    public MethodX() 
    { 
    } 
} 

然后,当请求http://..../ActionY url时,此方法将触发。

更多在菲尔的博客:How a Method Becomes An Action

编辑:好吧,也许这一个:直接在控制器类中定义的所有公共方法,而不是从基类继承,不重写那些在基类,除非你递归确定那些基本方法已经是行动,没有用NoAction属性装饰。

+1

“在控制器的所有方法都被认为操作,除了非公开方法。” - 不正确,ToString()是一个公共方法,但不是一个操作方法。 – 2009-07-06 14:08:56

+0

要添加到此,您还可以将一个[NonAction]属性添加到公共方法中,如果您需要将它公开用于单元测试目的。 – 2009-07-06 14:09:11

+0

好的,那个显然不是,但你有一般的想法。您从控制器类继承,您定义的公共方法将成为您的操作。 – User 2009-07-06 14:10:54

1

对于我在用作参考的ASP.NET MVC书籍中如何处理动作方法有一个非常好的解释。因为它发生,相关的网页都可以在谷歌图书:

http://books.google.com/books?id=Xb3a1xTSfZgC&lpg=PA308&ots=J9GgXhsads&dq=action%20method%20selection%20sanderson&pg=PA310

在情况下,链接死了,这是第310 Pro的ASP.NET MVC框架由史蒂芬·桑德森。

不知道它会帮助你找出如何编写单元测试,但它可能会帮助您按照反射代码...

相关问题