C# MVC(4)和EF(4)中导航属性的验证

C# MVC(4)和EF(4)中导航属性的验证,c#,asp.net-mvc,entity-framework,validation,asp.net-mvc-4,C#,Asp.net Mvc,Entity Framework,Validation,Asp.net Mvc 4,我用EF创建了一个模型,然后在MVC中创建了一个控制器和视图。 模型类型A具有类型B的导航属性。因此,当我创建A时,我希望选择A B MVC向导创建控制器并仅查看为标量属性创建的字段。因此,我将A上的创建操作更改为: 没有写任何验证,它一定是在某个地方自动生成的。如何更正它以对照ViewData[B]集合ID检查值?问题是下拉列表的值是ID,但属性是B 您应该绑定到导航属性的FK。我不确定你的模式,如果这没有帮助,你应该张贴它 <div class="editor-field">

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

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


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

问题是下拉列表的值是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.B更改为model.BId,因此我找到了一种详细的方法,既可以吃蛋糕,也可以吃蛋糕,而不必为FK id添加额外的字段

我将我的后期创建操作更改为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);
}

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

<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>

使用visual studio断点并查看从何处获得此错误I can't:Create Post action test ModelState.IsValid,因此在我可以设置断点之前它是有效的。值必须是一个字符串,它最终会被放入HTML中。如果使用option.ToString,则会得到错误:System.Data.Entity.DynamicProxies.Company_0666b8a654dc2c6f1c8e3e01ad765af62c7d70e1d339e44c8f4f2131b1b24dbb9 Company是我场景中的B。不过,最好是绑定到FK属性而不是导航项,然后使用Id。您可以指向此项上的资源或对此进行解释吗?谢谢。我想我必须将FK ID放入我自己对A的部分定义中。所以我想这将验证FK只是一个标量属性。这将解决我的问题。我只是希望会有一些糖来验证下拉值回到实际ID,以确保FK的完整性。谢谢你的帮助。
The value '1' is invalid.
<div class="editor-field">
    @Html.DropDownListFor(model => model.BId,  (IEnumerable<SelectListItem>)ViewData["B"], "---- Select B ----")
    @Html.ValidationMessageFor(model => model.BId)
</div>
[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);
}
<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>
[HttpPost]
public ActionResult Create(A a){
   B b = db.Bs.Find(a.B.Id);
   a.B = b;
   db.As.Add(a);
   db.SaveChanges();
}