在使用多态时,控制器如何选择正确的操作?

时间:2014-01-05 16:45:32

标签: asp.net-mvc

我刚才意识到我多年来一直在使用的东西应该不起作用!考虑以下操作的多态性:

public ActionResult MyAction() { ... }

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyAction(String input) { ... }

很明显,当我们使用 GET 时,只有第一个仍然是有效的候选者,因为该属性会过滤掉后者。因此,它是明确的,每个人都很高兴。但是,如果我们使用 POST

跳转到代码中会怎么样?

乍一看,人们很容易发现,由于第一种方法是更一般的行动,后者更适合在这种特殊情况下使用“以涵盖特价” , 可以这么说。但那是人类的逻辑。我怀疑服务器的原因是这样的。

我已经查看了我可以在项目中找到的路线和其他文件,但据我所知,有一些黑魔法涉及。 :)

所以我的问题是:框架如何知道要选择什么?

需要跟进的问题是MVC版本是否有所不同。

2 个答案:

答案 0 :(得分:3)

我建议阅读Phil Haack的How a Method Becomes An Action,它应该回答你的问题。引用一些重要部分:

  

ActionSelectionAttribute

     

一旦我们识别出与当前操作名称匹配的Controller类的所有方法,我们需要通过查看应用于列表中方法的ActionSelectionAttribute的所有实例来进一步缩小列表。

     

此属性是属性的抽象基类,可以对操作方法可以响应的请求进行细粒度控制。此方法的API非常简单,只包含一个方法。

public abstract class ActionSelectionAttribute : Attribute
{
  public abstract bool IsValidForRequest(ControllerContext controllerContext,
      MethodInfo methodInfo);
}

然后再往下走一点:

  

最后,我们应该在列表中留下一个方法,然后调用者调用它。如果多个方法可以处理当前请求,则调用者抛出指示问题的异常。如果没有方法可以处理请求,则调用者在控制器上调用HandleUnknownAction()。

     

ASP.NET MVC框架包含此基本属性的一个实现,即AcceptVerbsAttribute。

本文接着解释了这个过程如何与AcceptVerbsAttribute一起使用,展示了一个与你的相似的例子。

答案 1 :(得分:1)

框架的确如你所做的那样:选择后一种行为是因为它被认为更具体。我没有检查过每个版本,但自从引入HttpPostAttribute以来,我认为这种行为没有改变。

但是,我已经多次下载了ASP.NET MVC源代码,我可以看到实现确实有所改变。有一段时间,RunSelectionFilters ActionMethodSelector方法中源代码的相关部分如下所示:

// if a matching action method had a selection attribute, consider it more 
// specific than a matching action method without a selection attribute
return (matchesWithSelectionAttributes.Count > 0) 
  ? matchesWithSelectionAttributes 
  : matchesWithoutSelectionAttributes;

但这不是当前的实现。在the source code on codeplex right now中,实现有点复杂,但行为是相同的,参见RunSelectionFilters(...)的{​​{1}}内的评论:

ActionMethodSelectorBase.cs