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

ASP.NET MVC创建Client时报key为City的IEnumerable类型ViewData异常

问题根因

报错由两个问题共同导致:

  1. POST动作中,当ModelState验证失败返回视图时,没有重新给ViewBag.Cities赋值。HTTP是无状态协议,GET请求阶段写入ViewBag的数据不会保留到POST请求,此时视图渲染下拉框时找不到数据源,就会抛出指定key不存在的异常。
  2. 模型绑定逻辑错误:Client实体中的City是复杂类型的导航属性,下拉框提交的是城市Id(int类型值),直接绑定到复杂类型无法正确映射数据,即使绕过报错也无法正确保存客户关联的城市信息。
修复方案
  • 第一步:为Client实体添加城市外键属性,用于接收下拉框提交的选中值
using System.ComponentModel.DataAnnotations.Schema;

public class Client
{
    [Key]
    public int Id { get; set; }
    public string Surname { get; set; }
    public string Name { get; set; }
    // 新增外键字段,存储选中城市的ID
    public int CityId { get; set; }
    [ForeignKey(nameof(CityId))]
    public City City { get; set; }       
}

public class City
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}
  • 第二步:重构控制器代码,抽出下拉列表加载公共逻辑,GET和POST验证失败场景都要加载城市数据
private readonly ApplicationDbContext _context;

public ClientsController(ApplicationDbContext context)
{
    _context = context;
}

// 公共方法:加载城市下拉列表数据到ViewBag
private void LoadCitiesSelectList(int? selectedCityId = null)
{
    ViewBag.Cities = new SelectList(_context.City.ToList(), "Id", "Name", selectedCityId);
}

// GET: Clients/Create
public IActionResult Create()
{
    LoadCitiesSelectList();
    return View();
}

// POST: Clients/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Surname,Name,Patronymic,Telephone,CityId,Adress,SeriaNumberPassport,IdentificalCode")] Client client)
{
    if (ModelState.IsValid)
    {
        _context.Add(client);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    // 验证失败时重新加载下拉列表数据,否则视图找不到数据源会报错
    LoadCitiesSelectList(client.CityId);
    return View(client);
}
  • 第三步:修正视图代码,将下拉框绑定到外键字段,同时修正原标签的属性书写错误
<div class="form-group mb-3">
    <label asp-for="CityId" class="control-label">城市</label>
    @Html.DropDownListFor(model => model.CityId, ViewBag.Cities as SelectList, "请选择城市", new { @class = "form-select" })
    <span asp-validation-for="CityId" class="text-danger"></span>
</div>

额外修正:原div标签把mb-3写在了class属性外面,会导致样式失效,上述代码已经修复;同时增加了下拉框默认空选项和字段验证提示,避免用户未选择城市直接提交。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 00:31:04