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

ASP.NET Core 7 MVC:如何向控制器提交IEnumerable模型?

问题分析与解决:提交表单后IEnumerable模型接收为空

问题概述

基于IEnumerable<SkupinaKlientiVykazyModel>实现的表格视图渲染正常,但提交表单后控制器接收的模型始终为空。相关代码如下:

视图代码

@model IEnumerable<SkupinaKlientiVykazyModel>

<form method="post" asp-action="VykazSkupinaCreateMiddle2" id="KlientiSkupinyForm" asp-controller="Work">
    <div class="row pt-4">
        <div class="col-10">
            <h2 class="text-primary">Zápis výkazu pro kliety skupiny:  @skupinaText </h2>
        </div>
        <div class="col-2 text-end">
        </div>
    </div>
    <br />
    <br />

    <table class="table table-hover" style="width:100%">
        <thead>
            <tr class="table-info">
                <th scope="col">
                    Klient
                </th>
                <th scope="col">
                    Přítomen
                </th>
            </tr>
        </thead>
        <tbody>
            @{
                int i = 0;
                foreach (var obj in Model)
                {
                    <input name="SkupinaKlientiVykazyModel[@i].Klient" value="@obj.Klient" hidden />
                    <input name="SkupinaKlientiVykazyModel[@i].Id" value="@obj.Id" hidden />
                    <input name="SkupinaKlientiVykazyModel[@i].Skupina" value="@obj.Skupina" hidden />
                    <input name="SkupinaKlientiVykazyModel[@i].UserId" value="@obj.UserId" hidden />
                    <input name="SkupinaKlientiVykazyModel[@i].KlientName" value="@obj.KlientName" hidden />
                    <tr class="@(i%2==0?"table-primary":"table-secondary")">
                        <td>
                            @obj.KlientName
                        </td>
                        <td>
                            <input type="checkbox" name="SkupinaKlientiVykazyModel[@i].Pritomen" checked="@obj.Pritomen" value="@obj.Pritomen" />
                            </td>
                    </tr>
                    i++;
                }
            }
        </tbody>
    </table>
    <div class="row mb-3">
        <div class="col-md-4">
            <a asp-controller="Work" asp-action="AktivniKlienti" class="btn btn-secondary" style="width:250px">Zpět na seznam klientu</a>
        </div>
        <div class="col-md-8 text-end">
            <button type="submit" class="btn btn-primary" style="width:250px"><i class="breadcrumb-item bi-pencil-square"></i> Založ výkazy</button>
        </div>
    </div>

</form>

渲染后的HTML片段

<tbody>
    <input name="SkupinaKlientiVykazyModel[0].Klient" value="3026" hidden />
    <input name="SkupinaKlientiVykazyModel[0].Id" value="6615" hidden />
    <input name="SkupinaKlientiVykazyModel[0].Skupina" value="121" hidden />
    <input name="SkupinaKlientiVykazyModel[0].UserId" value="18b4adfd-7b08-4390-a23e-06a338842c77" hidden />
    <input name="SkupinaKlientiVykazyModel[0].KlientName" value="Mia14Nia77 Milena Hus&#xE1;rkov&#xE1;" hidden />
    <tr class="table-primary">
        <td>
            Mia14Nia77 Milena Hus&#xE1;rkov&#xE1;
        </td>
        <td>
            <input type="checkbox" name="SkupinaKlientiVykazyModel[0].Pritomen" checked="checked" value="value" />
        </td>
    </tbody>

控制器代码

[HttpPost]
public IActionResult VykazSkupinaCreateMiddle2(IEnumerable<SkupinaKlientiVykazyModel> klienti)
{
        string? userId = _userManager.GetUserId(User);

        int id = klienti.First().Skupina;
        // etc ...
}

模型代码

public class SkupinaKlientiVykazyModel
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    [DisplayName("Skupina")]
    public int Skupina { get; set; }
    [DisplayName("Uživatel")]
    public string UserId { get; set; }
    [DisplayName("Klient id")]
    public int Klient { get; set; }
    [DisplayName("Přítomen")]
    public bool Pritomen { get; set; }
    [DisplayName("Klient")]
    public string KlientName { get; set; }
}

原因分析

  1. 表单字段命名前缀不匹配:控制器参数名为klienti,但视图中所有input的name前缀用的是SkupinaKlientiVykazyModel。ASP.NET Core模型绑定要求字段name与参数名对应,才能正确映射到集合。
  2. 复选框绑定错误:
    • 渲染后的复选框value为"value",而非布尔值"true",导致模型无法将字符串转换为bool类型。
    • 未勾选复选框时,浏览器不会提交该字段,模型中Pritomen属性会被默认设为false,但错误的value设置会干扰绑定逻辑。
  3. 隐藏字段位置不规范:隐藏input放在<tbody>的<tr>外部,不符合HTML表格结构规范,可能导致表单数据解析异常。

解决方法

1. 修正表单字段的name前缀

将所有input的name前缀从SkupinaKlientiVykazyModel[@i]改为klienti[@i],与控制器参数名保持一致。

2. 修复复选框的绑定逻辑

添加同名隐藏input,value设为"false",确保未勾选时也能提交对应值;同时将复选框的value设为"true",保证勾选时提交正确的布尔值。

修改后的视图代码示例

@model IEnumerable<SkupinaKlientiVykazyModel>

<form method="post" asp-action="VykazSkupinaCreateMiddle2" id="KlientiSkupinyForm" asp-controller="Work">
    <div class="row pt-4">
        <div class="col-10">
            <h2 class="text-primary">Zápis výkazu pro kliety skupiny:  @skupinaText </h2>
        </div>
        <div class="col-2 text-end">
        </div>
    </div>
    <br />
    <br />

    <table class="table table-hover" style="width:100%">
        <thead>
            <tr class="table-info">
                <th scope="col">
                    Klient
                </th>
                <th scope="col">
                    Přítomen
                </th>
            </tr>
        </thead>
        <tbody>
            @{
                int i = 0;
                foreach (var obj in Model)
                {
                    <tr class="@(i%2==0?"table-primary":"table-secondary")">
                        <td>
                            @obj.KlientName
                            <!-- 将隐藏字段移到<tr>内部,规范结构 -->
                            <input name="klienti[@i].Klient" value="@obj.Klient" hidden />
                            <input name="klienti[@i].Id" value="@obj.Id" hidden />
                            <input name="klienti[@i].Skupina" value="@obj.Skupina" hidden />
                            <input name="klienti[@i].UserId" value="@obj.UserId" hidden />
                            <input name="klienti[@i].KlientName" value="@obj.KlientName" hidden />
                        </td>
                        <td>
                            <!-- 处理复选框:添加隐藏字段确保未勾选时提交false -->
                            <input type="hidden" name="klienti[@i].Pritomen" value="false" />
                            <input type="checkbox" name="klienti[@i].Pritomen" value="true" @(obj.Pritomen ? "checked" : "") />
                        </td>
                    </tr>
                    i++;
                }
            }
        </tbody>
    </table>
    <div class="row mb-3">
        <div class="col-md-4">
            <a asp-controller="Work" asp-action="AktivniKlienti" class="btn btn-secondary" style="width:250px">Zpět na seznam klientu</a>
        </div>
        <div class="col-md-8 text-end">
            <button type="submit" class="btn btn-primary" style="width:250px"><i class="breadcrumb-item bi-pencil-square"></i> Založ výkazy</button>
        </div>
    </div>

</form>

验证效果

修改后,渲染的input name会变成klienti[0].XXX,复选框勾选时提交true,未勾选时提交false,ASP.NET Core模型绑定就能正确将表单数据映射到IEnumerable<SkupinaKlientiVykazyModel> klienti参数中。

内容的提问来源于stack exchange,提问作者Jan Šalomoun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:04:55