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

ASP.NET MVC中DropDownList显示正常但失效,报ViewData项不存在错误

问题分析与解决方案

这个报错的核心原因很明确:当ASP.NET MVC渲染你的DropDownList时,找不到键为ScreeningId的、类型为IEnumerable<SelectListItem>的ViewData项。通常这个问题出现在两个场景里,咱们一步步拆解修复:

1. 常见错误场景与原因

场景1:GET请求加载Create页面时,未注入选项集合

如果你的ReservationsController的Create GET方法里,没有把放映场次(Screening)的选项集合放到ViewData/ViewBag中,页面渲染时自然找不到对应的下拉选项数据。

场景2:POST请求验证失败后,未重新填充选项集合

当用户提交表单触发Model验证失败时,你返回视图的过程中没有重新填充下拉选项集合——因为ViewData是单次请求有效的,POST回发后之前GET请求设置的ViewData会被清空。

2. 具体修复步骤

假设你的Reservation模型包含ScreeningId属性(用于绑定下拉选择值),咱们从控制器和视图两方面修正:

第一步:修正Reservations控制器代码

确保在GET初始加载和POST验证失败回显时,都填充好下拉选项集合:

public class ReservationsController : Controller
{
    private YourDbContext db = new YourDbContext(); // 替换成你的数据库上下文

    // GET: Reservations/Create
    public ActionResult Create()
    {
        // 将放映场次转换为SelectList,存入ViewData,键名要和DropDownList的目标键一致(这里是ScreeningId)
        // 参数说明:数据源、选项值字段、选项显示文本字段
        ViewData["ScreeningId"] = new SelectList(db.Screenings, "Id", "ScreeningName");
        return View();
    }

    // POST: Reservations/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Reservation reservation)
    {
        if (ModelState.IsValid)
        {
            db.Reservations.Add(reservation);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        // 关键!验证失败返回视图时,必须重新填充选项集合,同时指定用户之前选中的值(第四个参数)
        ViewData["ScreeningId"] = new SelectList(db.Screenings, "Id", "ScreeningName", reservation.ScreeningId);
        return View(reservation);
    }
}

第二步:修正Create视图代码

推荐使用强类型的DropDownListFor(更安全,避免键名匹配错误):

@model YourNamespace.Models.Reservation

@{
    ViewBag.Title = "Create Reservation";
}

<h2>Create New Reservation</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-group">
        @Html.LabelFor(m => m.ScreeningId, "Select Screening", new { @class = "control-label" })
        <div>
            <!-- 第二个参数是ViewData里的选项集合,第三个参数是默认提示文本 -->
            @Html.DropDownListFor(m => m.ScreeningId, 
                               (IEnumerable<SelectListItem>)ViewData["ScreeningId"], 
                               "Please select a screening", 
                               new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.ScreeningId, "", new { @class = "text-danger" })
        </div>
    </div>

    <!-- 其他表单字段 -->

    <div class="form-group">
        <input type="submit" value="Submit Reservation" class="btn btn-primary" />
    </div>
}

3. 进阶优化:使用ViewModel(推荐)

如果想避免ViewData/ViewBag的键名匹配问题,可以创建专门的ViewModel来封装表单数据和下拉选项:

public class ReservationViewModel
{
    public Reservation Reservation { get; set; }
    public IEnumerable<SelectListItem> ScreeningOptions { get; set; }
}

控制器代码调整:

public ActionResult Create()
{
    var vm = new ReservationViewModel
    {
        ScreeningOptions = new SelectList(db.Screenings, "Id", "ScreeningName")
    };
    return View(vm);
}

[HttpPost]
public ActionResult Create(ReservationViewModel vm)
{
    if (ModelState.IsValid)
    {
        db.Reservations.Add(vm.Reservation);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    // 重新填充选项
    vm.ScreeningOptions = new SelectList(db.Screenings, "Id", "ScreeningName", vm.Reservation.ScreeningId);
    return View(vm);
}

视图代码调整:

@model YourNamespace.ViewModels.ReservationViewModel

<!-- ...其他代码... -->

@Html.DropDownListFor(m => m.Reservation.ScreeningId, 
                   Model.ScreeningOptions, 
                   "Please select a screening", 
                   new { @class = "form-control" })

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:21:34