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

Asp.Net Core 6 MVC中如何将二维JavaScript数组从视图传至控制器

问题分析与解决方案

你的代码存在几个关键问题,导致数据无法正确传递到控制器,以下是逐一修正方案:

1. 修正ViewModel结构

你的SalesFormDataViewModel中SalesItemList是string[],但前端传递的是二维数组,类型不匹配,无法自动绑定。应该创建一个专门的销售项模型来接收数据:

// 新增销售项模型
public class SalesItemViewModel
{
    public string ProductId { get; set; }
    public string ProductName { get; set; }
    public decimal Price { get; set; }
    public int Quantity { get; set; }
    public decimal SubTotal { get; set; }
}

// 修改原ViewModel
public class SalesFormDataViewModel
{
    public string StoreId { get; set; }
    public decimal Total { get; set; }
    public List<SalesItemViewModel> SalesItemList { get; set; }
}

2. 修正前端数据组装与Ajax提交逻辑

你错误地混合了FormData和JSON.stringify,而且没有传递防伪令牌,导致请求被拦截。直接用JSON格式提交数据更适合这种场景:

// 确保salesItemsArray的结构和SalesItemViewModel字段对应
$('.btn-sales-add').on('click', function () {
    // 直接构建对象,而非数组,后端绑定更方便
    let salesItem = {
        ProductId: $('#product-id').val(),
        ProductName: $('#product-id option:selected').text(),
        Price: parseFloat($('#sales-price').val()),
        Quantity: parseInt($('#sales-quantity').val()),
        SubTotal: parseFloat($('#sales-sub-total').val())
    };

    total += salesItem.SubTotal;
    $('#sales-total input').val(total);

    salesItemsArray.push(salesItem); // 现在数组里是对象,不是子数组
});

// 提交部分的代码修改
let storeId = $("#sales-store-id").val();
let total = parseFloat($("#sales-total input").val());
let salesItemList = salesItemsArray;

// 组装符合ViewModel结构的JSON数据
var postData = {
    StoreId: storeId,
    Total: total,
    SalesItemList: salesItemList
};

// 获取防伪令牌(需要在视图里添加@Html.AntiForgeryToken())
let token = $('input[name="__RequestVerificationToken"]').val();

$.ajax({
    url: '/api/sales/createSales',
    method: 'POST',
    contentType: 'application/json',
    headers: {
        'RequestVerificationToken': token // 带上防伪令牌
    },
    data: JSON.stringify(postData),
    success: function (response) {
        alert('success');
    },
    error: function (xhr, status, error) {
        console.log(xhr.responseText); // 打印错误详情,方便排查
        alert('error: ' + xhr.responseText);
    }
});

3. 修正控制器配置

  • 确保控制器类上有[Route("api/sales")]特性,否则路由/api/sales/createSales无法匹配
  • 如果不需要验证防伪令牌(不推荐)可以暂时注释掉[ValidateAntiForgeryToken],但生产环境必须保留,所以一定要在Ajax里带上令牌

修正后的控制器示例:

[Route("api/sales")]
[ApiController] // 添加ApiController特性,自动启用模型验证和绑定
public class SalesController : ControllerBase
{
    [HttpPost]
    [Route("createSales")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> CreateSales(SalesFormDataViewModel salesFormDataViewModel)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState); // 返回验证错误,方便前端排查
        }
        // 后续保存到数据库的逻辑
        return Ok(new { success = "Stock updated successfully" });
    }
}

4. 视图中添加防伪令牌

在你的销售创建视图里,添加防伪令牌的HTML:

@Html.AntiForgeryToken()

额外排查要点

  • 打开浏览器开发者工具(F12),查看Network标签,检查请求的状态码和请求体,确认数据格式是否正确
  • 检查Sales、SalesProducts实体类的字段是否和ViewModel匹配,后续保存数据时需要正确映射

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:35:23