3

我遇到了试图使用@ Html.DropDownListFor()的问题。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) 

下拉列表正在呈现,并且一切似乎都很好un直到我提交表格。 HttpPost Create方法在ModelState.IsValid上返回false并抛出Model Error:从类型'System.String'到类型'... Models.Vendor'的参数转换失败,因为没有类型转换器可以在这些类型之间进行转换。

如果我通过让页面后,我结束了一个服务器错误: 异常详细信息:System.ArgumentNullException:值不能为空。 参数名称:项目

高低搜索后,我一直无法找到@ Html.DropDownListFor()不能正确自动绑定供应商对象到导航属性的原因。

任何帮助将不胜感激。

编辑: 我最终不得不显式设置ForeignKey属性,以便我可以直接访问“Vendor_Id”,然后我将DropDownListFor更改为指向“Vendor_Id”而不是导航属性。这似乎工作。

回答

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() 
           }); 
} 

这会很好地区分关注点并保持控制器整洁。

祝你好运

+0

您不应该使用ViewBag传入视图数据。你可以使用视图模型。我无法在这里发布代码,这是不可读的。下午我和我会让你知道;) – Ninglin

+0

同意。这是很久以前的事了。我想到了MVC 3.视图模型绝对是要走的路。 – TheGwa

0

我已经在下面的stackoverflow问题中回答了类似的问题。答案也适用于这个问题。

Validation for Navigation Properties in MVC (4) and EF (4)

这种做法并没有公布在控制器中的SelectList。我不认为在控制器中发布SelectList是个好主意,因为这意味着我们正在关注控制器中的视图部分,这显然不是问题的分离。