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

JavaScript新增行在ASP.NET Core保存后无法被后端获取的问题

动态添加行后后端无法接收数据的解决方法

问题场景

定义了以下C#实体类:

public class Tires {
  public int ID { get; set; }
  public string ArName { get; set; }
  public string EnName { get; set; }
  public Boolean IsMain { get; set; }
  public List<TireRecord> NewRecords { get; set; }
}
public class TireRecord {
  public string ArName { get; set; }
  public string EnName { get; set; }
  public bool IsMain { get; set; }
}

通过Razor视图和JavaScript实现动态添加行功能,前端可以正常新增行,但点击保存按钮后,后端Controller无法获取到新增行的数据,仅能接收初始加载的行数据。

原Razor视图代码

@model WebApplication6.Models.Tires

@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <form method="post" asp-action="Index" asp-controller="Tires">
        <h4>Tires</h4>
        <hr />

       <table>
           <thead>
              <tr>
                  <th>Arabic Name</th>
                  <th>English Name</th>
                 <th>Is Active</th>
             </tr>
         </thead>
         <tbody id="table-body">
             @for (var i = 0; i < Model.NewRecords.Count; i++)
             {
                 <tr>
                    <td><input type="text" asp-for="NewRecords[i].ArName" /></td>
                   <td><input type="text" asp-for="NewRecords[i].EnName" /></td>
                  <td><input type="checkbox" asp-for="NewRecords[i].IsMain" /></td>
             </tr>
        }
   </tbody>
      </table>

     <button type="button" id="add-button">Add</button>
    <button type="submit" id="save-button">Save</button>
    <div>
   <a asp-action="Index">Back to List</a>
    </div>
   </form>

  <script>
 const addButton = document.getElementById('add-button');
 const tableBody = document.getElementById('table-body');
 let newRowCounter = @Model.NewRecords.Count;

   addButton.addEventListener('click', () => {
 newRowCounter++;

  const newRow = document.createElement('tr');
newRow.innerHTML = `<td><input type="text" name="NewRecords[${newRowCounter}].ArName" /></td>
  <td><input type="text" name="NewRecords[${newRowCounter}].EnName" /></td>
  <td><input type="checkbox" name="NewRecords[${newRowCounter}].IsMain" /></td>`;
      tableBody.appendChild(newRow);
 });
  </script>
</body>
</html>

原Controller代码

IRepositories<Tires> Tires_;
public List<TireRecord> NewRecords { get; set; }

Tires model;
public TiresController(IRepositories<Tires> Tires1)
{
    Tires_ = Tires1;
    NewRecords = new List<TireRecord>();

   model = new Tires
    {
        // Initialize other properties if needed
        NewRecords = new List<TireRecord>() // Initialize the NewRecords property
    };
}
[HttpPost]
public IActionResult Index(Tires model)
{
    // 原代码未实现保存逻辑
    return RedirectToAction("DisplayRecords");
}
public ActionResult Index()
{
    return View(model);
}

问题原因

  1. 索引不连续:ASP.NET MVC的模型绑定要求集合类型的字段索引必须从0开始连续递增。原JS代码中先执行newRowCounter++再使用索引,导致新增行的索引跳过了已有行的下一个连续值(比如已有1行时索引为0,新增行直接用索引2),模型绑定无法识别非连续索引的字段。
  2. 复选框未提交默认值:未选中的复选框不会向服务器提交任何值,而bool类型的属性需要明确的false值才能完成绑定,原动态新增的行缺少对应的隐藏字段来提交未选中状态。

解决步骤

1. 修正前端JavaScript代码

调整索引生成逻辑,先使用当前newRowCounter作为索引,再自增;同时为复选框添加对应的隐藏字段,确保未选中时提交false值:

const addButton = document.getElementById('add-button');
const tableBody = document.getElementById('table-body');
let newRowCounter = @Model.NewRecords.Count;

addButton.addEventListener('click', () => {
    // 使用当前counter作为索引,之后再自增
    const currentIndex = newRowCounter;
    newRowCounter++;

    const newRow = document.createElement('tr');
    newRow.innerHTML = `
        <td><input type="text" name="NewRecords[${currentIndex}].ArName" /></td>
        <td><input type="text" name="NewRecords[${currentIndex}].EnName" /></td>
        <td>
            <input type="hidden" name="NewRecords[${currentIndex}].IsMain" value="false" />
            <input type="checkbox" name="NewRecords[${currentIndex}].IsMain" value="true" />
        </td>
    `;
    tableBody.appendChild(newRow);
});

2. 完善Controller的保存逻辑

在HttpPost方法中添加将数据保存到数据库的逻辑:

[HttpPost]
public IActionResult Index(Tires model)
{
    if (ModelState.IsValid)
    {
        // 保存Tires实体到数据库
        Tires_.Add(model); // 或根据你的仓储实现调用对应的保存方法
        Tires_.SaveChanges(); // 提交更改
    }
    return RedirectToAction("DisplayRecords");
}

3. 验证初始数据加载

确保Get方法中正确初始化NewRecords集合,避免空引用:

public ActionResult Index()
{
    // 确保NewRecords已初始化,避免视图中循环报错
    if (model.NewRecords == null)
    {
        model.NewRecords = new List<TireRecord>();
    }
    return View(model);
}

原理说明

ASP.NET MVC的模型绑定器通过字段名称中的索引(如NewRecords[0].ArName)来识别集合元素,只有当索引连续且从0开始时,才能正确将所有元素绑定到List<TireRecord>中。同时,为复选框添加隐藏字段后,无论是否选中,都会向服务器提交一个明确的值(true或false),确保bool类型属性的绑定正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:35:54