DropDownListFor&导航属性

时间:2011-08-09 22:41:04

标签: asp.net-mvc-3 navigation properties html.dropdownlistfor

我遇到了一个试图使用@ 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”而不是导航属性。这似乎有效。

2 个答案:

答案 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是个好主意,因为这意味着我们正在处理控制器中的视图部分,这显然不是关注点的分离。