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

.NET Core 如何将前端JS动态添加行的HTML表格转为控制器端列表并存入数据库

嘿,这个场景我太熟了!其实核心就是让前端动态生成的表单元素名称符合.NET Core的模型绑定规则,这样后端就能直接把表格行数据接收成列表。我给你一步步讲清楚怎么实现:

第一步:定义后端模型与接收接口

首先得先创建一个对应表格行数据的实体类,每个属性对应表格的一列:

public class TableRowData
{
    // 这里替换成你表格实际的字段,比如姓名、年龄、邮箱等
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

然后在控制器里写一个POST接口,直接用List<TableRowData>作为参数,.NET Core的模型绑定会自动把前端传来的数据转换成列表:

[HttpPost]
public IActionResult SaveTableRows(List<TableRowData> tableRows)
{
    // 到这里tableRows已经是所有表格行的集合了,直接存入数据库就行
    // 示例:用EF Core批量添加
    // _context.TableRows.AddRange(tableRows);
    // await _context.SaveChangesAsync();
    
    return Ok("数据保存成功");
}
第二步:前端表格与动态添加逻辑

你的表格要放在<form>标签里,动态添加行的时候,必须让每个输入框的name属性遵循tableRows[index].字段名的格式,这里的index是连续的数字(从0开始),这是模型绑定能识别的关键。

基础HTML结构

<form id="tableForm" method="post" asp-action="SaveTableRows">
    <table id="dataTable">
        <thead>
            <tr>
                <th>姓名</th>
                <th>年龄</th>
                <th>邮箱</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <!-- 初始第一行,index从0开始 -->
            <tr>
                <td><input type="text" name="tableRows[0].Name" required /></td>
                <td><input type="number" name="tableRows[0].Age" required /></td>
                <td><input type="email" name="tableRows[0].Email" required /></td>
                <td><button type="button" onclick="deleteRow(this)">删除</button></td>
            </tr>
        </tbody>
    </table>
    <button type="button" onclick="addNewRow()">添加新行</button>
    <button type="submit">提交保存</button>
</form>

动态添加/删除行的JavaScript

// 添加新行
function addNewRow() {
    const tableBody = document.getElementById('dataTable').querySelector('tbody');
    const rowCount = tableBody.rows.length;
    const newRow = document.createElement('tr');
    
    // 重点:用当前行数作为新的index,保证name格式正确
    newRow.innerHTML = `
        <td><input type="text" name="tableRows[${rowCount}].Name" required /></td>
        <td><input type="number" name="tableRows[${rowCount}].Age" required /></td>
        <td><input type="email" name="tableRows[${rowCount}].Email" required /></td>
        <td><button type="button" onclick="deleteRow(this)">删除</button></td>
    `;
    tableBody.appendChild(newRow);
}

// 删除行并更新索引
function deleteRow(button) {
    const row = button.parentElement.parentElement;
    row.remove();
    
    // 关键:删除行后必须重新更新剩余行的index,否则中间断号会导致模型绑定丢失数据
    const tableBody = document.getElementById('dataTable').querySelector('tbody');
    Array.from(tableBody.rows).forEach((row, index) => {
        const inputs = row.querySelectorAll('input');
        inputs.forEach(input => {
            // 替换name里的旧索引为新的连续索引
            input.name = input.name.replace(/\[(\d+)\]/, `[${index}]`);
        });
    });
}
几个重要的注意事项
  • 索引必须连续:如果删除行后不更新索引,比如剩下[0]和[2],.NET Core只会识别[0]的数据,[2]会被忽略,这是模型绑定的规则。
  • AJAX提交也适用:如果不想用表单提交,用AJAX序列化表单数据或者构造数组发送,后端接收方式完全一样。比如用fetch提交时,记得带上ASP.NET Core的防伪造令牌。
  • 支持其他表单控件:不管是复选框、下拉框还是文本域,只要name属性符合格式,模型绑定都能正确识别。

内容的提问来源于stack exchange,提问作者Ramazan Musluoğlu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 22:07:46