【问题标题】:DropDownListFor & Navigation PropertiesDropDownListFor & 导航属性
【发布时间】:2011-08-09 22:41:03
【问题描述】:

我在尝试使用 @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:值不能为空。 参数名称:项目

在高低搜索之后,我找不到 @Html.DropDownListFor() 没有正确地将供应商对象自动绑定到导航属性的原因。

任何帮助将不胜感激。

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

【问题讨论】:

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


    【解决方案1】:

    我发现最好的方法如下。更改控制器以创建 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 的代码移动到您的存储库中,并将其放入名为 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()
                                   });
    }
    

    这可以很好地分离关注点并保持控制器整洁。

    祝你好运

    【讨论】:

    • 您不应该使用 ViewBag 来传递视图数据。您应该使用视图模型。我不能在这里发布代码,它不可读。私信我,我会告诉你;)
    • 同意。这是很久以前的事了。我认为围绕 MVC 3。视图模型绝对是要走的路。
    【解决方案2】:

    我在下面的 stackoverflow 问题中回答了类似的问题。这个问题的答案也很好。

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

    这种方法不会在控制器中发布 SelectList。我不认为在控制器中发布 SelectList 是个好主意,因为这意味着我们正在处理控制器中的视图部分,这显然不是关注点分离。

    【讨论】:

      猜你喜欢
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-10
      • 2019-12-17
      • 1970-01-01
      相关资源
      最近更新 更多