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

.NET 6 Razor页面动态添加参与者模型绑定失败问题排查

问题原因与修复方案

核心问题

你遇到的模型绑定失败,是因为客户端JavaScript动态生成的asp-for标签不会被Razor服务器端解析。asp-for是Razor的服务器端指令,用来生成输入框的name和id属性,但JS在客户端拼接的HTML里,这个指令不会被处理,导致新增行的输入框没有正确的name属性,服务器无法识别这些参数,自然无法完成模型绑定。

另外你的代码还有两个次要问题:

  • 动态生成的行和删除按钮使用了重复的id(inputRow、removeRow),违反HTML唯一ID的规范,可能导致JS选择元素出错。
  • 删除行后索引不连续,即使修复了name属性,非连续的索引也可能导致模型绑定跳过部分项。

修复后的代码

视图代码(修正一处笔误)

原视图里的d-table-cellead是笔误,改成d-table-cell,其余不变:

<p class="lead">Les invités</p>
<div class="d-flex justify-content-end mb-1">
    <button id="addRow" type="button" class="btn btn-outline-dark ms-auto">Ajouter une personne</button>
</div>
<table class="w-100 mb-5" id="newRow">
    <tr>
        <th>Prénom</th>
        <th>Nom de famille</th>
        <th></th>
    </tr>
    <tr class="inputRow">
        <td>
            <input type="text" class="form-control d-table-cell" asp-for="Participation.Participants[0].Prenom" />
            <span class="text-danger" asp-validation-for="Participation.Participants[0].Prenom"></span>
        </td>
        <td>
            <input type="text" class="form-control d-table-cell" asp-for="Participation.Participants[0].Nom" />
            <span class="text-danger" asp-validation-for="Participation.Participants[0].Nom"></span>
        </td>
        <td></td>
    </tr>
</table>

脚本代码(核心修改)

@section Scripts
{
<script>
    var rowCount = 1;

    function updateDeleteButtons() {
        $('#newRow .inputRow').each(function (index) {
            // 只显示最后一行的删除按钮
            $(this).find('.removeRow').toggle(index === rowCount - 1);
        });
        // 重新同步所有行的索引,保证连续
        reindexRows();
    }

    function reindexRows() {
        $('#newRow .inputRow').each(function (index) {
            // 更新Prénom输入框的name和id
            $(this).find('input[name*="Prenom"]').attr({
                'name': `Participation.Participants[${index}].Prenom`,
                'id': `Participation_Participants_${index}__Prenom`
            });
            // 更新Nom输入框的name和id
            $(this).find('input[name*="Nom"]').attr({
                'name': `Participation.Participants[${index}].Nom`,
                'id': `Participation_Participants_${index}__Nom`
            });
            // 更新验证提示的for属性
            $(this).find('span[data-valmsg-for*="Prenom"]').attr('data-valmsg-for', `Participation.Participants[${index}].Prenom`);
            $(this).find('span[data-valmsg-for*="Nom"]').attr('data-valmsg-for', `Participation.Participants[${index}].Nom`);
        });
        rowCount = $('#newRow .inputRow').length;
    }

    $("#addRow").click(function () {
        var html = '';
        html += '<tr class="inputRow">';
        html += '<td>';
        // 手动构造name属性,不用asp-for
        html += `<input type="text" class="form-control d-table-cell" name="Participation.Participants[${rowCount}].Prenom" id="Participation_Participants_${rowCount}__Prenom" />`;
        html += `<span class="text-danger" data-valmsg-for="Participation.Participants[${rowCount}].Prenom" data-valmsg-replace="true"></span>`;
        html += '</td>';
        html += '<td>';
        html += `<input type="text" class="form-control d-table-cell" name="Participation.Participants[${rowCount}].Nom" id="Participation_Participants_${rowCount}__Nom" />`;
        html += `<span class="text-danger" data-valmsg-for="Participation.Participants[${rowCount}].Nom" data-valmsg-replace="true"></span>`;
        html += '</td>';
        html += '<td>';
        html += '<button type="button" class="btn btn-danger removeRow">Supprimer</button>';
        html += '</td>';
        html += '</tr>';

        $('#newRow').append(html);
        rowCount++;
        updateDeleteButtons();
    });

    $(document).on('click', '.removeRow', function () {
        $(this).closest('.inputRow').remove();
        updateDeleteButtons();
    });
</script>
}

关键修改说明

  1. 替换asp-for为手动构造name属性:
    客户端无法解析Razor指令,所以直接按照模型绑定要求的格式生成name(比如Participation.Participants[1].Prenom),服务器就能正确识别参数并绑定到List<ParticipantDto>。

  2. 移除重复ID,改用class:
    把id="inputRow"改成class="inputRow",id="removeRow"改成class="removeRow",避免ID冲突导致的JS选择错误。

  3. 新增reindexRows函数:
    删除行后,重新遍历所有输入行,更新它们的name、id和验证提示的属性,保证索引从0开始连续,这样模型绑定能正确读取所有项,不会因为索引断层而丢失数据。

  4. 修正视图笔误:
    原视图中第二列输入框的class="form-control d-table-cellead"是笔误,改成d-table-cell保证样式统一。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:30:56