0

我用 EF 创建了一个模型,然后在 MVC 中创建了一个控制器和视图。模型类型A具有要键入的导航属性B。因此,当我创建时,A我想选择一个B.

MVC 向导创建控制器并仅查看为标量属性创建的字段。因此,我将创建操作更改A为:

public ActionResult Create() //Create action for A
{
    List<B> b = db.B.ToList(); //db is my DataContext

    ViewData["B"] = companies.Select(option => new SelectListItem
                    {
                        Text = (option.Name.ToString()),
                        Value = (option.Id.ToString())
                    });
    return View();
}

并添加到我的观点:

<div class="editor-label">
    @Html.LabelFor(model => model.B)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.B,  (IEnumerable<SelectListItem>)ViewData["B"], "---- Select B ----")
    @Html.ValidationMessageFor(model => model.B)
</div>

到目前为止一切都很好,我得到了 HTML

<select class="valid" id="B" name="B">
    <option value="">---- Select B ----</option>
    <option selected="selected" value="1">TestB</option>
</select>

但是,当我提交时,我收到错误:

The value '1' is invalid.

没有编写任何验证,它一定是在某处自动生成的。如何更正它以检查 ViewData["B"] 集合 ID 的值?

4

3 回答 3

1

问题是您的下拉列表的值是Id- 但属性是B.

您应该改为绑定到导航属性的 FK。我不确定你的模型(如果这没有帮助你应该发布它)

<div class="editor-field">
    @Html.DropDownListFor(model => model.BId,  (IEnumerable<SelectListItem>)ViewData["B"], "---- Select B ----")
    @Html.ValidationMessageFor(model => model.BId)
</div>

注意我已更改model.Bmodel.BId

于 2012-08-25T19:47:44.260 回答
0

所以我找到了一种(冗长的)方法来吃蛋糕并吃掉它,而不必为 FK id 输入额外的字段

我将 POST 创建操作更改为 FormCollection 格式。

[HttpPost]
public ActionResult Create(FormCollection collection) //POST create for A
{
    A a = new A();

    a.Name = collection["Name"];
    a.Description = collection["Description"];

    try
    {
        int bId = Int32.Parse(collection["B"]);
        a.B = db.B.First(option => option.Id == bId);
        ValidateModel(a);
    }
    catch
    {
        ModelState.AddModelError("B", new Exception("bId does not match an existing B"));
    }

    if (ModelState.IsValid)
    {
        db.A.Add(a);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    //Failed
    //Go back to create form
    List<B> blist = db.B.ToList();

    ViewData["B"] = blist.Select(option => new SelectListItem
    {
        Text = (option.Name.ToString()),
        Value = (option.Id.ToString())
    });

    return View(a);
}
于 2012-08-25T21:38:33.787 回答
0

另一种不添加额外字段(A 类上的 BId)或从 FormCollection 读取模型字段的方法是直接在视图中绑定 model.b.Id。

<div class="editor-label">
    @Html.LabelFor(model => model.B)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.B.Id,  (IEnumerable<SelectListItem>)ViewData["B"], "---- Select B ----")
    @Html.ValidationMessageFor(model => model.B)
</div>

此绑定将 Id 绑定到 A 的导航属性 B。要绑定 Name 属性,我们需要从数据库上下文中读取 B 一次。

[HttpPost]
public ActionResult Create(A a){
   B b = db.Bs.Find(a.B.Id);
   a.B = b;
   db.As.Add(a);
   db.SaveChanges();
}
于 2016-05-26T21:31:04.237 回答