我用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的值?
答案 0 :(得分: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.B
更改为model.BId
答案 1 :(得分: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);
}
答案 2 :(得分: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属性,我们需要从数据库上下文中读取一次。
[HttpPost]
public ActionResult Create(A a){
B b = db.Bs.Find(a.B.Id);
a.B = b;
db.As.Add(a);
db.SaveChanges();
}