ASP.NET Core MVC中AJAX内联编辑报400错误的问题排查与方案问询
ASP.NET Core MVC 行内联编辑AJAX 400错误修复及优化方案
问题核心原因
- 重复DOM ID:循环渲染表格行时,每个行的
idVal、bgnTxtIn、endTxtIn重复,导致JS获取的值始终是第一行数据,参数传递错误。 - 缺少防伪令牌验证:Controller的Post Action添加了
[ValidateAntiForgeryToken],但AJAX请求未携带该令牌,直接触发400错误。 - 请求数据格式不匹配:AJAX默认用form-urlencoded格式传递嵌套对象,ASP.NET Core参数绑定异常;同时Action返回
RedirectToAction不适合AJAX场景,应返回JSON结果。 - 参数绑定逻辑冲突:Action同时接收
int id和MainTexts mainTexts,易导致ID不匹配,增加绑定复杂度。
修复步骤
步骤1:修正视图中的重复ID问题
将循环内的ID改为class,确保每行元素唯一:
@foreach (var item in Model) { <tr> <td class="maintxtId"> <span class="idVal">@item.Id</span> </td> <td class="maintxtBegin"> <span class="beginTxtSpan">@item.BeginText</span> <input class="bgnTxtIn" type="text" value="@item.BeginText" style="display:none"/> </td> <td class="maintxtEnd"> <span class="endTxtSpan">@item.EndText</span> <input class="endTxtIn" type="text" value="@item.EndText" style="display:none" /> </td> <td> <a class="Edit" href="javascript:;">Edit</a> <a class="Update" href="javascript:;" style="display:none">Update</a> <a class="Cancel" href="javascript:;" style="display:none">Cancel</a> <a class="Delete" href="javascript:;">Delete</a> </td> </tr> }
步骤2:更新AJAX请求,添加防伪令牌并修正数据获取
添加防伪令牌meta标签,改用JSON格式发送请求,获取当前行的正确数据:
@section scripts { <script src="~/lib/jquery/dist/jquery.min.js"></script> <meta name="csrf-token" content="@Html.AntiForgeryToken()" /> <script type="text/javascript"> $(document).ready(function () { // 原有编辑逻辑保持不变 $("body").on("click", '#tstTable .Edit', function () { var row = $(this).closest("tr"); $("td", row).each(function () { if ($(this).find("input").length > 0) { $(this).find("input").show(); $(this).find("span").hide(); } }); row.find(".Update").show(); row.find(".Cancel").show(); row.find(".Delete").hide(); $(this).hide(); }); $("body").on("click", '#tstTable .Update', function () { var row = $(this).closest("tr"); // 同步输入值到span $("td", row).each(function () { if ($(this).find("input").length > 0) { var span = $(this).find("span"); var input = $(this).find("input"); span.html(input.val()); span.show(); input.hide(); } }); row.find(".Edit").show(); row.find(".Delete").show(); row.find(".Cancel").hide(); $(this).hide(); // 获取当前行的正确数据 var MaintxtViewModel = { Id: parseInt(row.find(".idVal").text()), BeginText: row.find(".bgnTxtIn").val(), EndText: row.find(".endTxtIn").val() }; $.ajax ({ type: 'POST', url: "/ReqArea/MainTexts/Edit", contentType: "application/json; charset=utf-8", headers: { "RequestVerificationToken": $('meta[name="csrf-token"]').attr("content") }, data: JSON.stringify(MaintxtViewModel), success: function (result) { alert(result.success ? "保存成功" : "保存失败:" + result.message); }, error: function (xhr) { alert("请求错误:" + xhr.statusText); } }); }); }); </script> }
步骤3:修改Controller的Post Action,适配AJAX请求
移除多余参数,返回JSON结果,简化绑定逻辑:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit([Bind("Id,BeginText,EndText")] MainTexts mainTexts) { if (!ModelState.IsValid) { return Json(new { success = false, message = "数据验证失败" }); } try { _context.Update(mainTexts); await _context.SaveChangesAsync(); return Json(new { success = true, message = "保存成功" }); } catch (DbUpdateConcurrencyException) { if (!MainTextsExists(mainTexts.Id)) { return Json(new { success = false, message = "数据不存在" }); } else { throw; } } }
优化实现方案
- 使用DTO(数据传输对象):创建
MainTextEditDto仅包含编辑所需字段,避免直接暴露实体类,提升安全性和性能。 - 局部视图渲染行:将表格行抽为
_MainTextRow.cshtml局部视图,简化主视图代码,便于维护。 - 添加加载状态:AJAX请求时禁用Update按钮并显示加载动画,优化用户体验。
- 客户端验证:集成jQuery Validate实现前端验证,提前拦截无效数据,减少服务器请求。
- RESTful风格路由:使用
[Route("api/[controller]/[action]")]定义规范的API路由,提升代码可读性。
内容的提问来源于stack exchange,提问作者Developer
相关产品推荐
相关产品推荐

