当ASP MVC控制器操作被修饰为[HttpPost]时,出现“404未找到”错误。

9

我有一个控制器操作方法,当它看起来像这样时可以工作:

public ActionResult testMethod(int id)
{
    //do something...
    //return something...
    return View();
}

但是当我指定它应该是“Post”方法时,我收到了一个'404未找到错误':
[HttpPost]
public ActionResult testMethod(int id)
{
    //do something...
    //return something...
    return View();
}

我在同一个控制器中有其他的POST和GET控制器动作方法,它们都可以正常工作。但是这个不行?发生了什么事?(我确定我漏掉了一些显而易见的东西...)

更新: 一个ajax调用请求控制器方法: var id = 1;

$.ajax({
    url: '/indices/testMethod/',
    data: id,
    type: 'POST',
    success: function (data) {
        //Do something
    }
});

我也尝试使用Postman测试该方法,确保发送了POST请求。

更新2: 我尝试将参数更改为id,并尝试确保所有方法和url位置都大写以匹配,但没有任何效果。

在Fiddler中,我可以看到实际上正在进行GET请求,即使我在ajax调用中指定了POST请求,所以现在我需要找出为什么请求最终被发送为GET而不是POST。

我还尝试包含一个属性路由描述,就像这样

    [HttpPost]
    [Route("indices/TestMethod/{id:int}")]
    public ActionResult TestMethod(int id)

然后尝试使用不同的url进行ajax调用:

$.ajax({
    url: '/indices/TestMethod/1',
    data: id,
    type: 'POST',
    success: function (data) {
        var tr = 123;
        var yr = data;
        //Do something
    }
});

启用属性路由后,参数值在URL中,我在Fiddler中看到首先发生了POST请求,它得到了301状态错误,但随后也发生了GET请求,它得到了404错误。
更新3: 经过更多调查,我成功地缩小了问题定义范围,这使得开启一个新的问题是有意义的。该问题可以在此处找到: ASP MVC jQuery $.ajax POST请求不会调用控制器方法,但在“新”MVC项目中可以工作 这个问题似乎是由于内容安全策略设置导致的。

5
你确定请求是使用POST方法发送到指定动作,而不是其他的请求方式吗?安装Fiddler并检查请求数据。 - asawyer
1
您可以通过使用@Html.ActionLink来生成目标URL,从而避免URL的歧义。只需提供控制器和操作名称即可。 - Panagiotis Kanavos
你是否传递了 param1 参数?因为它是必需的。 - JamieD77
如果您在最后一个示例中将“type”更改为“GET”,并在jQuery中使用相同的URL,那么该方法是否被调用?您是否尝试过使用$.post而不是$.ajax,以确保您没有错过任何其他配置? - PzYon
当我将类型更改为GET并使用相同的URL时,该方法确实被调用。但是,使用$.post而不是4.ajax仍然无法运行。 - Proposition Joe
显示剩余6条评论
2个回答

2
尝试将param1更改为id并查看是否有效。这听起来很愚蠢,但实际上我自己曾经遇到过类似的问题,并且这种方法解决了问题。
我能想到的另一个问题是,在您的应用程序中,testMethod的路径为/Indices/TestMethod,其中包含大写字符。当您请求/indices/testMethod/时可能会发生一些重定向,导致GET请求。
尝试更改ajax调用中的url或尝试添加[Route()]属性以设置路由名称。

我曾经遇到过类似的问题。更改参数没有任何影响。解决问题的方法是在URL中使用小写字母。 - Savage

1
您可能需要将int param1参数添加FromBody属性,因为它是一个简单类型?更多信息请参见此处
否则,期望的路由格式为/indices/testMethod/{param1}(即使是POST请求,参数也必须在URL中)。这条路线可能没有定义,例如在您的global.asax.cs中。例如,您可以尝试向/indices/testMethod/1发出POST请求,只是为了尝试是否真的是路由问题?
如果您确实遇到路由问题,可以使用Attribute Routing为您的方法定义特定路由。至少对于测试/开发来说,这使得更容易看到/理解为您的方法实际定义的路由。
一些进一步的问题以缩小范围,确定实际可能存在的问题:
  • dataGoesHere对象是什么格式?
  • 有效的POST方法长什么样子?它们的参数是哪种数据类型?引用类型还是值类型?
  • 你注册了哪些路由?(即在global.asax.cs中)

更新

我会尝试像这样定义控制器方法:

[HttpPost]
[Route("indices/TestMethod/")]
public ActionResult TestMethod([FromBody] int id)

像这样定义动作调用:

$.ajax({
    url: '/indices/TestMethod/',
    data: id, // alternatively try: {id: id}
    type: 'POST',
    success: function (data) { }
});

要么尝试将id作为简单值传递,要么尝试使用带有id属性的对象进行传递(请参见上面的注释)。

1
如果是这种情况,参数将为空(如果是引用,则为null,如果是int,则为0)。操作者无法调用action。这与缺少参数无关。 - Panagiotis Kanavos
@PanagiotisKanavos:我们如何知道作者尝试不同场景时使用的URL是哪个?我们又如何知道哪些路由实际上被定义了?如果param1不是UrlParameter.Optional,那么我认为当调用/indices/testMethod/(没有进一步参数)时,该方法的路由不匹配。 - PzYon
@PzYon:你的答案是正确的,[FromBody] 是方法标识的一个必要部分。 - Ed_le_fou
路由机制不使用请求正文来识别要调用的控制器方法,将 FromBody 添加到参数声明中可能仅在模糊地确定参数必须来自哪里时需要强制绑定参数的一种方式。无论参数是简单类型还是复杂类型,都可以在没有 FromBody 的情况下来自正文。该属性只会影响从被调用方法中观察到的参数值,而不会影响原则上定位方法的能力。 - GSerg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接