用 [HttpPost] 装饰时 ASP MVC 控制器操作“未找到 404”错误

Posted

技术标签:

【中文标题】用 [HttpPost] 装饰时 ASP MVC 控制器操作“未找到 404”错误【英文标题】:ASP MVC controller action '404 not found' error when decorated with [HttpPost] 【发布时间】:2015-12-27 00:09:03 【问题描述】:

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

public ActionResult testMethod(int id)

    //do something...
    //return something...
    return View();

但是当我指定它应该是“发布”方法时,我得到一个“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 而不是作为发布。

我也试过包含一个属性路由描述,像这样

    [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 request does not call controller method, but works in "fresh" MVC project

此问题似乎是由对此项目处于活动状态的内容安全策略设置引起的。

【问题讨论】:

您如何尝试联系此操作? 您确定请求是 POST 到动作,而不是其他动词吗?安装 Fiddler 并检查请求数据。 添加了一些额外的信息 - 据我所知,发送了一个 POST 请求,但由于我收到 404 错误,它从未到达控制器。 使用 Fiddler 查看实际发送的内容。您可能调用了错误的 URL - 您使用的是相对于根目录的 url,而不是当前页面。如果您的网站托管在例如http://someroot/somesubsite,您的代码将调用http://someroot/indices/testMethod/,而不是http://someroot/somesubsite/indices/testMethod 您可以使用@html.ActionLink 通过提供控制器和动作名称来生成目标ULR,从而避免URL 歧义 【参考方案1】:

尝试将param1 更改为id,看看是否有效。这听起来可能很愚蠢,但实际上我在自己之前遇到过你的问题并且解决了问题。

我能想到的另一个问题是,在您的应用中,testMethod 的路径是带有大写字符的/Indices/TestMethod。当您请求/indices/testMethod/ 时,可能会发生一些重定向,从而导致GET 请求。

尝试更改 ajax 调用中的 url 或尝试添加 [Route()] 属性来设置路由名称。

【讨论】:

我遇到了类似的问题。更改参数没有任何区别。解决方法是在 url 中使用小写字母。【参考方案2】:

您可能需要将FromBody-属性添加到int param1-参数,因为它是一个简单类型?请参阅here 了解更多信息。

否则,需要格式为 /indices/testMethod/param1 的路由(即参数必须在 URL 中,即使它是 POST 请求)。此路线可能未定义,即在您的global.asax.cs 中。例如,您可以尝试向/indices/testMethod/1 发出 POST 请求。只是尝试一下是否真的是路由问题?

如果您的路由确实存在问题,您可以使用Attribute Routing 为您的方法定义一个特定的路由。至少对于测试/开发而言,这样可以更轻松地查看/理解实际为您的方法定义的路由。

一些额外的问题可以缩小范围,它实际上可能是什么:

dataGoesHere-object 有什么格式? 工作的 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-property 的对象一起传递(参见上面的评论)。

【讨论】:

如果是这种情况,参数将为空(如果是引用,则为 null,如果为 int,则为 0)。 OP 根本无法调用 action。这与缺少参数无关 @PanagiotisKanavos:我们如何知道作者使用哪个 URL 尝试他提到的不同场景?我们怎么知道实际定义了哪些路线?如果param1 不是UrlParameter.Optional,那么我认为在调用/indices/testMethod/(没有其他参数)时该方法的路由不匹配。 @PzYon:你的回答是对的,[FromBody]是方法识别的重要组成部分。 路由机制不使用请求体来识别要调用的控制器方法,在参数声明中添加FromBody可能只需要强制一种方式绑定参数参数必须来自何处是模棱两可的。不管参数是简单类型还是复杂类型,它都可能来自没有FromBody的body。该属性只会影响被调用方法观察到的参数值,原则上不会影响方法定位能力。

以上是关于用 [HttpPost] 装饰时 ASP MVC 控制器操作“未找到 404”错误的主要内容,如果未能解决你的问题,请参考以下文章

如何将模型作为参数传递给 ASP.NET MVC 中的 [HttpPost] ActionMethod?

asp.net mvc 用多个枚举装饰 [Authorize()]

HTTP 错误 405 | [HttpPost] ASP.NET MVC 核心 3.1

长时间运行的 ASP.NET MVC 核心控制器 HTTPPost 方法超时

[HttpPost] ASP.NET中有啥作用???

ASP.NET MVC API与JS进行POST请求时传递参数 -CHPowerljp原创