HtmlHelper 如何知道数据在 ViewBag 上?

How HtmlHelper know data is on the ViewBag?

我正在观看有关 HtmlHelper 下拉菜单的教程 https://www.youtube.com/watch?v=79aYSOcmpV8

8 分钟左右,他正在读取数据库以替换一些硬编码值。

To pass list of Departments from the controller, store them in "ViewBag"

public ActionResult Index()
{
    // Connect to the database
    SampleDBContext db = new SampleDBContext();
    // Retrieve departments, and build SelectList
    ViewBag.Departments = new SelectList(db.Departments, "Id", "Name");

    return View();
}

最后一步。

Now in the "Index" view, access Departments list from "ViewBag"

@Html.DropDownList("Departments", "Select Department") 

我在视图中没有看到强类型模型。


那么 Helper 怎么知道 Departments 引用了 ViewBag 中的值?

当您将值添加到 ViewBag 时,它也会在生成视图时添加到 ViewContextViewData 属性。您使用的 DropDownList() 重载相当于在

中传递 null SelectList
@Html.DropDownList("Departments", null, "Select Department")

在这种情况下,助手会在内部搜索 ViewData 属性 以找到一个匹配的键,它是 IEnumerable<SelectListItem>"Departments" 是)。可以在source code

private static MvcHtmlString SelectInternal()方法中看到相关代码
// If we got a null selectList, try to use ViewData to get the list of items.
if (selectList == null)
{
    selectList = htmlHelper.GetSelectData(name);
    ....
}

请注意,本教程中的示例是一种糟糕的方法,它使用 'magic' 字符串并要求您使用 Request.Form["Departments"] 访问 POST 方法中的值。更好的方法是使用视图模型并强绑定到您的视图模型,例如

public class MyViewModel
{
    public int SelectedDepartment { get; set; }
    public IEnumerable<SelectListItem> DepartmentList { get; set; }
    ...
}

GET 方法是

public ActionResult Create()
{
    MyViewModel model = new MyViewModel
    {
        DepartmentList = new SelectList(db.Departments, "Id", "Name");
    };
    return View(model);
}

并在视图中

@model MyViewModel
....
@Html.DropDownListFor(m => m.SelectedDepartment, Model.DepartmentList, "Select Department")

和post表格返回

[HttpPost]
public ActionResult Create(MyViewModel model)