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
相关产品推荐
相关产品推荐

