这是在创建新控制器时从VS Add New Scaffolded Item...
获取的。
在控制器中:
// GET: Drivers/Create
public ActionResult Create()
{
ViewBag.Tenant = new SelectList(db.Tenants, "TenantID", "TenantName");
return View();
}
视图然后呈现一个下拉列表:
@Html.DropDownListFor(model => model.Tenant, null, htmlAttributes: new { @class = "form-control" })
相关型号信息:
public partial class Driver
{
public int DriverID { get; set; }
public int Tenant { get; set; }
public virtual Tenant Tenant1 { get; set; }
}
public partial class Tenant
{
public Tenant()
{
this.Drivers = new HashSet<Driver>();
}
public int TenantID { get; set; }
public string TenantName { get; set; }
public virtual ICollection<Driver> Drivers { get; set; }
}
有人可以解释为什么会这样吗?
我查看了其他问题和文档但找不到答案。我怀疑它是“约定优于配置”的东西,它是使用属性的名称从ViewBag
拉出来的。实际上,我将ViewBag
属性更改为Tenantz
并获得以下异常:
没有类型为'IEnumerable'的ViewData项 有关键'租户'。
那么设置ViewBag
的属性名称是否与要更新良好实践的模型属性相同?看起来没问题,但我总是听说你应该如何避免ViewBag
和动态类型。
答案 0 :(得分:6)
正如您已经发现的那样,有一个惯例。您视图中的以下行:
@Html.DropDownListFor(model => model.Tenant, null, htmlAttributes: new { @class = "form-control" })
与此行完全相同:
@Html.DropDownList("Tenant", null, htmlAttributes: new { @class = "form-control" })
现在,如果您看一下如何在源代码中实现DropDownList
帮助器,您会注意到它只是这样做:
object obj = htmlHelper.ViewData.Eval(name) as IEnumerable<SelectListItem>;
其中name
是传递给DropDownList
助手的第一个参数。你猜怎么着?它会发现您在控制器中设置的相应值:ViewBag.Tenant = ...
。
据说使用ViewBag是绝对的,灾难性的,非常糟糕的做法。你已经找到了原因。它可以像狗一样咬你,甚至不知道发生了什么。防止这些狗(ViewBag
)的最好方法是在你的解决方案中搜索它们并给它们毒药。只需删除代码中的所有ViewBag
调用,并使用视图模型。然后你不会得到不好的惊喜,一切都会有一个合理的解释,在StackOverflow上没有必要这样的问题。
例如,您可以编写普通视图模型:
public class DriverViewModel
{
public int? SelectedTenantID { get; set; }
public IEnumerable<SelectListItem> Tenants { get; set; }
}
和一个正常的控制器操作,它将在数据存储区中查询所需信息并将实体模型投影到视图模型:
// GET: Drivers/Create
public ActionResult Create()
{
var viewModel = new DriverViewModel();
viewModel.Tenants = new SelectList(db.Tenants, "TenantID", "TenantName");
return View(viewModel);
}
最后是相应的强类型视图:
@model DriverViewModel
...
@Html.DropDownListFor(
model => model.SelectedTenantID,
Model.Tenants,
htmlAttributes: new { @class = "form-control" }
)
在这种情况下,您使用强类型视图,具有强类型视图模型和帮助程序。不再有任何疑虑(和狗咬)。代码是可读的,你不能问,为什么这个约定超过配置正在做这个或那个。因此,只要您的应用程序中没有ViewBag的痕迹,就不会有这样的问题。