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

ASP.NET Core Razor Pages 为List类型模型属性创建表单多值录入遇问题求助

现有代码问题点

  • JS中使用getElementById获取class为Category-Container的容器,返回值为null,导致添加元素逻辑执行报错,这是只能添加2个输入框的核心原因
  • 动态生成的input的name属性不符合Razor Pages集合绑定规则,后端无法正确映射到绑定属性
  • asp-for直接绑定List<T>类型的Addresses/Categories本身是错误的,应该绑定到泛型类的内部属性
  • 集合属性没有初始化空实例,服务端渲染初始表单时会触发空引用异常

修复方案

1. 修正Model定义

为Address、Category补充业务属性,同时初始化集合避免空引用:

public class Address
{
    // 示例属性,可根据业务调整
    public string Street { get; set; }
}
public class Category
{
    // 示例属性,可根据业务调整
    public string Name { get; set; }
}
public class FormInput 
{
    public List<Address> Addresses { get; set; } = new();
    public List<Category> Categories { get; set; } = new();
}

2. 修正Razor页面HTML

给容器添加正确的id,初始输入框使用带索引的绑定规则:

<form method="post">
    <!-- 地址模块 -->
    <ul id="AddressContainer">
      <li class="row">
        <div class="col-8">
            <input asp-for="_Input.Addresses[0].Street" type="text" class="w-100" />
        </div>
        <div class="col">
            <button type="button" class="btn btn-primary" onclick="AddNewItem('AddressContainer', '_Input.Addresses', 'Street')">
            新增地址
            </button>
        </div>
      </li>
    </ul>

    <!-- 分类模块 -->
    <ul id="CategoryContainer">
      <li class="row">
        <div class="col-8">
            <input asp-for="_Input.Categories[0].Name" type="text" class="w-100" />
        </div>
        <div class="col">
            <button type="button" class="btn btn-primary" onclick="AddNewItem('CategoryContainer', '_Input.Categories', 'Name')">
            新增分类
            </button>
        </div>
      </li>
    </ul>
    <button type="submit">提交表单</button>
</form>

3. 重写JS动态添加逻辑

按照Razor集合绑定规则生成name属性,通用方法支持多字段复用:

function AddNewItem(containerId, fieldPrefix, propertyName) {
    const container = document.getElementById(containerId);
    // 计算当前已有项数量作为新项的索引,索引必须从0开始连续递增
    const currentIndex = container.querySelectorAll('li').length;

    const row = document.createElement('li');
    row.classList.add('row');
    
    // 组装输入框
    const inputCol = document.createElement('div');
    inputCol.classList.add('col-8');
    const input = document.createElement('input');
    input.classList.add('w-100');
    // 核心:name格式必须为 绑定属性名[索引].子属性名
    input.name = `${fieldPrefix}[${currentIndex}].${propertyName}`;
    input.type = 'text';
    inputCol.appendChild(input);
    
    // 组装按钮
    const btnCol = document.createElement('div');
    btnCol.classList.add('col');
    const addBtn = document.createElement('button');
    addBtn.classList.add('btn', 'btn-primary');
    addBtn.innerText = '新增';
    addBtn.type = 'button';
    addBtn.onclick = () => AddNewItem(containerId, fieldPrefix, propertyName);
    btnCol.appendChild(addBtn);
    
    row.appendChild(inputCol);
    row.appendChild(btnCol);
    container.appendChild(row);
}

注意事项

  • Razor Pages集合绑定的核心要求是name属性的索引从0开始连续不中断,只要符合该规则,添加任意数量的输入框都可以正常提交
  • 如果业务需要支持删除表单项,删除后需要遍历剩余输入框重新赋值索引,避免索引中断导致后端漏收数据
  • 不需要保留每行新增按钮的话,可以把新增按钮移到容器外部,索引计算逻辑保持不变即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 11:18:01