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); }
问题原因
- 索引不连续:ASP.NET MVC的模型绑定要求集合类型的字段索引必须从0开始连续递增。原JS代码中先执行
newRowCounter++再使用索引,导致新增行的索引跳过了已有行的下一个连续值(比如已有1行时索引为0,新增行直接用索引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
相关产品推荐
相关产品推荐

