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

