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árková" hidden /> <tr class="table-primary"> <td> Mia14Nia77 Milena Husárková </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; } }
原因分析
- 表单字段命名前缀不匹配:控制器参数名为
klienti,但视图中所有input的name前缀用的是SkupinaKlientiVykazyModel。ASP.NET Core模型绑定要求字段name与参数名对应,才能正确映射到集合。 - 复选框绑定错误:
- 渲染后的复选框value为
"value",而非布尔值"true",导致模型无法将字符串转换为bool类型。 - 未勾选复选框时,浏览器不会提交该字段,模型中
Pritomen属性会被默认设为false,但错误的value设置会干扰绑定逻辑。
- 渲染后的复选框value为
- 隐藏字段位置不规范:隐藏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
相关产品推荐
相关产品推荐

