You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vanilla JavaScript Ajax请求无法向Controller传递参数

原生JavaScript Ajax无法传递Id到ASP.NET Core Controller的解决方法

问题描述

使用原生JavaScript编写的Ajax请求无法将Id参数从前端传递到Controller的Action方法:

  • 调试确认前端JavaScript中Id存在有效值(如值为'2')
  • 已为Controller Action添加[HttpPost]特性,请求能成功命中方法,但Controller端始终接收Id为null

相关代码

Html视图

<tbody>
    @foreach(var item in Model.CartList)
    {
        <tr>
            <td>@item.Product.Name</td>
            <td>@item.ProductFragranceName</td>
            <td>@item.ProductWeightName</td>
            <td>@item.Price.Value.ToString("c")</td>
            <td><button type="button" data-cartid="@item.Id" class="btn btn-danger delete_from_cart" data-requesturl="@Url.Action("RemoveCart", "Cart", new { Area = "" })"><i class="bi bi-trash-fill"></i></button></td>
        </tr>
    }
</tbody>

JavaScript代码

//Define Namespace
var Cart = Cart || {};

document.addEventListener("DOMContentLoaded", function (docEvent) {

    let cartDeleteButtons = document.querySelectorAll('.delete_from_cart');

    cartDeleteButtons.forEach(deleteButton => {
        deleteButton.addEventListener('click', function (e) {
            let cartId = deleteButton.dataset.cartid;
            let cartRemoveRequestURL = deleteButton.dataset.requesturl;
            Cart.RemoveFromCart(cartId, cartRemoveRequestURL);
        })
    });
}); // end doc ready

Cart.RemoveFromCart = function (id, requestURL) {
    // Create the XMLHttpRequest object.
    const xhr = new XMLHttpRequest();
    // Initialize the request
    xhr.open("POST", requestURL, true);
    // Set content type
    xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
    // Send the request with data to post
    xhr.send(
        JSON.stringify({
            id: id
        })
    );
    // Fired once the request completes successfully 
    xhr.onload = function (e) {
        // Check if the request was a success
        if (this.readyState === XMLHttpRequest.DONE && this.status === 201) {
            // Get and convert the responseText into JSON
            var response = JSON.parse(xhr.responseText);
            console.log(response);
        }
    }
}

Controller方法

public async Task<IActionResult> RemoveCart(int id)
{
    var dbCart = await _dbContext.ShoppingCarts.FirstOrDefaultAsync(sc => sc.Id == id);
    if (dbCart != null)
    {
        _dbContext.ShoppingCarts.Remove(dbCart);
        await _dbContext.SaveChangesAsync();
    }
    return RedirectToAction(nameof(Index));
}

解决方案

方案1:为Controller参数添加[FromBody]特性

ASP.NET Core默认不会从JSON请求体绑定简单类型参数(如int),需要显式添加[FromBody]特性告知框架从请求体读取数据:

[HttpPost]
public async Task<IActionResult> RemoveCart([FromBody] int id)
{
    var dbCart = await _dbContext.ShoppingCarts.FirstOrDefaultAsync(sc => sc.Id == id);
    if (dbCart != null)
    {
        _dbContext.ShoppingCarts.Remove(dbCart);
        await _dbContext.SaveChangesAsync();
    }
    return RedirectToAction(nameof(Index));
}

方案2:确保参数类型匹配

前端从dataset获取的id是字符串类型,可手动转换为数字后再发送,避免类型不匹配导致绑定失败:

xhr.send(
    JSON.stringify({
        id: parseInt(id)
    })
);

方案3:改用URL参数传递Id

如果不想使用请求体传递,可将Id拼接到请求URL中,此时无需[FromBody]特性:

Cart.RemoveFromCart = function (id, requestURL) {
    const xhr = new XMLHttpRequest();
    // 将Id作为查询参数拼接到URL
    xhr.open("POST", `${requestURL}?id=${id}`, true);
    // 无需设置JSON类型的Content-Type
    xhr.send();
    
    xhr.onload = function (e) {
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
            console.log("删除成功");
            // 刷新页面更新购物车状态
            window.location.reload();
        }
    }
}

对应的Controller方法保持[HttpPost]和原参数即可:

[HttpPost]
public async Task<IActionResult> RemoveCart(int id)
{
    // 原有逻辑...
}

原因说明

ASP.NET Core的模型绑定规则中,简单类型(如int、string)默认优先从查询字符串(QueryString)、**路由数据(RouteData)或表单数据(FormData)**中绑定,而非JSON请求体。因此当通过JSON请求体传递简单类型参数时,必须使用[FromBody]特性显式指定绑定来源。

内容的提问来源于stack exchange,提问作者JakeFromStateFarm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 22:32:03