404 - 在控制器Y上找不到公共操作方法X(ActionInvoker.InvokeAction返回false)

Die*_*ego 39 .net asp.net-mvc .net-4.0 asp.net-mvc-3

这不是一个重复的问题,这个问题让我发疯.我收到典型错误"在控制器Y上找不到公共操作方法X",返回a 404 Not Found.截图给出了一个好主意:

Visual Studio调试会话

该图显示调试器在执行抛出异常的行之前暂停(base.HandleUnknownAction(actionName)).现在,在你得出结论之前,这里有一些信息:

  1. 这在某种程度上非常好.
  2. 操作GET应接受HTTP动词()UpdateCart(请参阅方法签名上方的注释).
  3. 发送的参数无关紧要:错误发生POST,GET参数的任意组合.
  4. 同一控制器中的其他类似操作效果很好.
  5. 我带了UpdateCart标记的截图virtual,但删除virtual没有区别.
  6. 屏幕截图显示ActionInvoker.InvokeAction(this.ControllerContext, "UpdateCart")返回false.不知道为什么在我的控制器上执行的反射无法找到方法,但它是正确的!

路由是默认路由并且它们可以工作,否则我将无法阻止调试器获取上面的屏幕截图.这是以下代码Global.asax.cs:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Tickets", action = "Index", id = UrlParameter.Optional } 
    );

}
Run Code Online (Sandbox Code Playgroud)

任何想法都非常感谢.

编辑

下面森·布朗的回答是正确的:HttpGetHttpPost是互斥的.解决方案是用这些属性替换[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)].

Eth*_*own 58

问题是你要指定HttpGetHttpPost属性.如果您将它们都关闭,则该操作将接受POST和GET请求.我的猜测是,HttpGetHttpPost属性不会向MVC发出信号以允许相应的请求类型,而是拒绝相反的类型.因此,通过包含[HttpPost],您拒绝GET请求,并通过包含[HttpGet],您拒绝POST请求...有效地拒绝所有请求类型.保持属性关闭,它将接受这两种类型.

更新:我刚检查了MVC源代码,我的假设是正确的.在ActionMethodSelector,它因此检查属性:

if (attrs.All(attr => attr.IsValidForRequest(controllerContext, methodInfo))) {
    matchesWithSelectionAttributes.Add(methodInfo);
}
Run Code Online (Sandbox Code Playgroud)

换句话说,对于要调用的操作,all ActionMethodSelectorAttribute(from HttpPostAttributeHttpGetAttributederived)必须返回true.一个或另一个总是返回false,因此操作永远不会执行.

  • 使用"因此"这个词.Upvoted. (4认同)