ASP.NET 控制器,AJAX GET 有效,但 POST 无效 (404)

Posted

技术标签:

【中文标题】ASP.NET 控制器,AJAX GET 有效,但 POST 无效 (404)【英文标题】:ASP.NET controller, AJAX GET works, but POST does not (404) 【发布时间】:2018-05-10 21:10:14 【问题描述】:

我有一个 .NET Core MVC 项目 (dotnet 2.0.0),我想从 .cshtml 视图向某个控制器方法发送 AJAX 请求。

我可以使用 GET 毫无问题地做到这一点。

AJAX:

var msg = 
    someField: "some value",
    someAnotherField: "another value"
    ;

jQuery.ajax(
    url: '@Url.Action("DoStuff", "Some")',
    dataType: 'application/json',
    data: msg,
    type: 'GET',
    success: function(data) 
        alert(data);
    
);

控制器:

public class SomeController : Controller

    public JsonResult DoStuff(Msg post)
    
        // some processing here
        // ...
        return Json("some result");
    

    public class Msg
    
        public string someField  get; set; 
        public string someAnotherField  get; set; 
    

但是当我尝试使用 POST...

修改了 AJAX(只是改变了它的类型):

// ...
type: 'POST',
// ...

修改控制器方法(只是添加了一个属性):

// ...
[HttpPost]
public JsonResult DoStuff(Msg post)
// ...

...我得到Failed to load resource: the server responded with a status of 404 (Not Found)

我尝试将[FromBody] 属性添加到控制器,但它没有改变任何东西(并且 GET 方法在没有它的情况下也可以正常工作)。我还为我的 AJAX data 尝试了 JSON.stringify() - 没有区别。

所以,我认为它与路由有关?或者也许将 JSON 对象作为参数传递给控制器​​对于 POST 请求是不同的?

更新

我创建了一个小项目 (uploaded to Dropbox) 来重现此问题,但我无法重现它。一切正常,只需更改为type: 'POST' 并添加[HttpPost] 就足够了。

所以,我的问题不在于 GET/POST 语义,而在于我的主项目中的一些设置/路由。我会尝试找出问题所在,并分享我的结果。

【问题讨论】:

对于帖子,使用路由属性,[HttpPost] 它就在那里,你可以在我的“修改后的控制器”代码中看到。 “修改后的控制器”是否在不同的控制器中?如果是这样,那么 ajax 将不会命中它,因为它指向“SomeController”。或者您的意思是它是完全相同的控制器,但您通过添加标签对其进行了修改? 这是同一个控制器,我只是添加了一个[HttpPost]属性。 检查控制台中的网络选项卡,看看请求本身是什么样子的。比较获取 ajax 和发布 ajax 时的样子。使用 get,它应该添加 `?msg=....' 但使用 post 你应该有 JSON。 【参考方案1】:

在 AJAX 请求中,将数据属性更改为如下所示的 POST

data: JSON.stringify(msg)

【讨论】:

是的,我已经尝试过了,但没有任何区别。而且在没有 JSON.stringify() 的情况下使用 GET 也可以正常工作。 您可以尝试更改 POST 方法的名称吗?我遇到了同样的问题,通过更改方法名称解决了问题。 不仅如此,我还尝试将方法移动到另一个具有真正唯一名称(控制器和方法)的控制器,但仍然失败。【参考方案2】:
    url = '@Url.Action("ControllerName", "MethodName")';
    $.ajax(
        url: url,
        method: 'post',
        dataType: 'json',
        async: false,
        data: dataParameter,
        success: function (data) 
            var vmMsg = data;
            if (vmMsg.MessageType == 1) 
                ShowNotification(1, vmMsg.CurrentMessage);

    

        ,
        error: function () 

        
    );

[HttpPost] 公共 ActionResult 方法名(参数) var data = _iMonthlyBillProvisionManager.ClientInterface(Param); 返回 Json(数据,JsonRequestBehavior.AllowGet);

【讨论】:

这是我已经拥有的,但在我的特定项目中不起作用,请参阅更新附录。【参考方案3】:

差不多两年后,在做一个不同的项目时,我终于发现了当时的问题。

所以我遇到了类似的情况,唯一不同的是这次我使用的是 .NET Core 2.2(比原来是 2.0),我得到的错误是405 Method Not Allowed(而不是 2.0 中的 404),这帮助我意识到这是因为缺少防伪令牌(我已全局启用这些令牌)。

找到实际原因后,很容易找到解决方案——我只需要在 XMLHttpRequest 中添加 RequestVerificationToken 标头即可。

Some.cshtml:

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf

@
    string antiForgeryToken = Xsrf.GetAndStoreTokens(Context).RequestToken;


...

<script>

    // with jQuery
    jQuery.ajax(
        url: '@Url.Action("DoSome", "SomeController")',
        dataType: "json",
        headers: 
            "RequestVerificationToken": "@(antiForgeryToken)"
        ,
        type: "POST",
        // ...

    // without jQuery
    let xhr = new XMLHttpRequest();
    xhr.responseType = "json";
    xhr.open("POST", '@Url.Action("DoSome", "SomeController")';
    xhr.setRequestHeader("RequestVerificationToken", "@(antiForgeryToken)");
    // ...

</script>

【讨论】:

以上是关于ASP.NET 控制器,AJAX GET 有效,但 POST 无效 (404)的主要内容,如果未能解决你的问题,请参考以下文章

如何从 jQuery ajax 调用将复杂对象传递给 ASP.NET WebApi GET?

Ajax 传递空值但控制器在 ASP.NET MVC 中为空

在 asp.net mvc 中对控制器进行简单的 Ajax 调用

在asp.net mvc中对控制器进行简单的Ajax调用

ASP.NET Core 模型未通过 AJAX 绑定到控制器

Asp.Net MVC 5 Jquery 验证不适用于带有提交事件的 ajax 帖子,显示为有效表单