我遇到了一个试图使用@ Html.DropDownListFor()的问题。
我有一个带有导航属性的模型:
public class Thing {
...
public virtual Vendor Vendor { get; set; }
}
在控制器中,我抓住供应商列表进入ViewBag:
public ActionResult Create() {
ViewBag.Vendors = Vendor.GetVendors(SessionHelper.CurrentUser.Unit_Id);
return View();
}
视图中的html项如下所示:
@Html.DropDownListFor(model => model.Vendor, new SelectList(ViewBag.Vendors, "Id", "Name"), "---- Select vendor ----")
@Html.ValidationMessageFor(model => model.Vendor)
正在呈现下拉列表,在提交表单之前一切正常。 HttpPost Create方法在ModelState.IsValid上返回false并抛出模型错误:从类型'System.String'到类型'... Models.Vendor'的参数转换失败,因为没有类型转换器可以在这些之间进行转换类型。
如果我让页面发布,我最终会遇到服务器错误: 异常详细信息:System.ArgumentNullException:Value不能为null。 参数名称:items
在搜索高低之后,我无法找到@ Html.DropDownListFor()未正确将Vendor对象自动绑定到导航属性的原因。
非常感谢任何帮助。
编辑: 我最终必须显式设置ForeignKey属性,以便我可以直接访问“Vendor_Id”,然后我将DropDownListFor更改为指向“Vendor_Id”而不是导航属性。这似乎有效。
答案 0 :(得分:3)
我发现最好的方法如下。更改控制器以创建SelectListItems。
public ActionResult Create() {
ViewBag.Vendors = Vendor.GetVendors(SessionHelper.CurrentUser.Unit_Id)
.Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.Name),
Value = option.Id.ToString()
});
return View();
}
然后按如下方式修改视图:
@Html.DropDownListFor(model => model.Vendor, (IEnumerable<SelectListItem>)ViewBag.Vendors, "---- Select vendor ----")
@Html.ValidationMessageFor(model => model.Vendor)
您必须将ViewBag.Vendors转换为(IEnumerable)。
这使视图保持整洁。您还可以将获取SelectListItems的代码移动到您的repo,并将其放在一个名为GetVendorsList()的方法中。
public IEnumerable<SelectListItem> GetVendorsList(int unitId){
return Vendor.GetVendors(unitId)
.Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.Name),
Value = option.Id.ToString()
});
}
这样可以很好地区分问题并使控制器保持整洁。
祝你好运答案 1 :(得分:0)
我在以下stackoverflow问题中回复了类似的问题。答案也适用于这个问题。
Validation for Navigation Properties in MVC (4) and EF (4)
此方法不会在控制器中发布SelectList。我不认为在控制器中发布SelectList是个好主意,因为这意味着我们正在处理控制器中的视图部分,这显然不是关注点的分离。