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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:35:02