ViewModel从视图传递至控制器为空问题排查求助
问题分析与解决方案
你的控制器中ModShopView模型为空的核心原因是ASP.NET Core的模型绑定无法识别你当前视图生成的表单字段名称,导致无法将表单数据映射到ViewModel对象上。
为什么会出现这个问题?
ASP.NET Core的模型绑定需要表单元素的name属性与ViewModel的属性结构匹配。你当前的视图里,input的name直接用了@Polozky.IdZbozi(比如某个商品的ID值,比如1),但你的ViewModel是ModShopView,里面包含IEnumerable<ModShop> EshopItems集合,模型绑定根本不知道这些零散的ID字段对应到集合里的哪个元素,自然无法填充mymodel对象。
修复步骤
1. 调整视图,生成符合模型绑定规则的表单字段
你需要用for循环(而非foreach)来遍历EshopItems,这样可以生成带索引的name属性(比如EshopItems[0].Mnozstvi),让模型绑定能正确识别并填充集合。
修改后的视图代码:
@model MojeIdentita.Models.ModShopView @using MojeIdentita.Helpers @{ string lang = (string)ViewContext.RouteData.Values["lang"] ?? "cz"; ViewData["Title"] = Html.GetLangResourceHtml(lang, "menuShop", true); } <h1 class="text-left" role="heading" aria-level="1">@Html.GetLangResourceHtml(lang, "menuShop", true)</h1> <div class=""> <div> @Html.Raw(Model.Description.FirstOrDefault().Part1) </div> @using (Html.BeginForm()) { @* 用for循环遍历,因为foreach无法生成索引绑定 *@ @for (int i = 0; i < Model.EshopItems.Count(); i++) { var Polozky = Model.EshopItems.ElementAt(i); <div class="row"> <div class="col-md-3 col-sm-6 col-xs-12 city"><p>@Polozky.NazevZbozi</p></div> <div class="col-md-3 col-sm-6 col-xs-12"><p>@Polozky.Vat</p></div> <div class="col-md-3 col-sm-6 col-xs-12"><p>@Polozky.Cena</p></div> <div class="col-md-3 col-sm-6 col-xs-12"> <p> @* 隐藏字段绑定IdZbozi,确保模型绑定能识别是哪个商品 *@ @Html.HiddenFor(m => m.EshopItems.ElementAt(i).IdZbozi) @* 输入框绑定Mnozstvi属性,name会自动生成EshopItems[i].Mnozstvi *@ @Html.TextBoxFor(m => m.EshopItems.ElementAt(i).Mnozstvi, new { @class = "form-control" }) </p> </div> </div> } <input type="submit" value="@Html.GetLangResourceHtml(lang, "txtObjednat", true)" class="order" /> } </div>
2. 简化控制器代码,直接使用绑定后的ViewModel
现在模型能正确绑定了,你不需要再通过IFormCollection来获取数据,可以直接从mymodel.EshopItems中拿到用户输入的数量:
[HttpPost] public IActionResult Shop(ModShopView mymodel) { if (!ModelState.IsValid) { // 如果模型验证失败,返回原视图显示错误 return View(mymodel); } string result = string.Empty; foreach (var item in mymodel.EshopItems) { if (item.Mnozstvi > 0) { result += $"Key={item.IdZbozi} value={item.Mnozstvi} název:{item.NazevZbozi}<br/>"; } } return Content($"result: {result}"); }
额外说明
- 为什么用
for循环?因为foreach遍历IEnumerable时,模型绑定无法生成带索引的字段名称,而for循环可以通过索引明确指定集合中的元素,让Html.TextBoxFor生成正确的name属性。 - 隐藏字段
HiddenFor的作用:确保每个商品的IdZbozi能被提交到服务器,这样你能知道哪个商品对应哪个数量。
内容的提问来源于stack exchange,提问作者Jan Šalomoun
相关产品推荐
相关产品推荐

