我正在尝试根据DropDownList的返回值设置导航属性(外键)。
我有以下数据模型:
(为简洁起见,省略了一些属性和细节。)
邀请,其中包含Guid ID和一组来宾。
public class Invite
{
public Guid InviteId { get; set; }
public virtual ICollection<Guest> Guests { get; set; }
}
来宾,邀请属性将其链接到邀请。
public class Guest
{
public virtual Invite Invite { get; set; }
}
在我的DataInitaliser中,我可以正确构建这些对象并将它们发送到数据库,例如:
new Invite()
{
InviteId = Guid.NewGuid(),
Name = "Bloggs",
AllDay = false,
Guests = new List<Guest>()
{
new Guest() { GuestId = Guid.NewGuid(), FirstName = "Joe", LastName = "Bloggs", Vip = false},
}
};
在我的GuestController中,我构建了可能的邀请列表,并将其添加到ViewBag中以便在视图中显示。
void PopulateInvite(object invite)
{
var query = db.Invites.Select(i => i).OrderBy(i => i.Name).ToList();
ViewBag.Invites = new SelectList(query, "InviteId", "Name", invite);
}
我在访客视图中显示对象列表,如下所示:
@model Models.Guest
<div class="form-group">
@Html.LabelFor(model => model.Invite, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.Invite, (IEnumerable<SelectListItem>)ViewBag.Invites, String.Empty)
@Html.ValidationMessageFor(model => model.Invite)
</div>
</div>
这会正确显示数据库中的预期值。
当我将值发布回GuestController时会出现问题。
创建的Post函数几乎是标准的支架。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include="GuestId,FirstName,LastName,Vegetarian,Attending,Vip,Invite")] Guest guest)
{
if (ModelState.IsValid)
{
guest.GuestId = Guid.NewGuid();
db.Guests.Add(guest);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
this.PopulateInvite(guest.Invite);
return View(guest);
}
我在这里挖了一下这个原因,我想我理解了潜在的问题。我的函数PopulateInvite
将InviteId
放入Guid的集合中,它作为String(不是Guid?)返回,无法转换为Invite对象。
"The parameter conversion from type 'System.String' to type 'Models.Invite' failed because no type converter can convert between these types."
我确实尝试更改我的PopulateInvite集合,因此它填充了一个实际的Invite对象,如下所示:
void PopulateInvite(object invite)
{
var query = db.Invites.Select(i => i).OrderBy(i => i.Name).ToList().Select(i =>
{
return new
{
Invite = new Invite() { InviteId = i.InviteId },
Name = i.Name
};
});
ViewBag.Invites = new SelectList(query, "Invite", "Name", invite);
}
然而,这也会因上述错误而失败,令人困惑的是我返回了对象的String表示,而不是实际的对象本身。
ModelState["Invite"].Value.RawValue
{string[1]}
[0]: "Models.Invite"
那么......根据表单中的帖子设置导航属性的方法是什么?
我应该在ModelState.IsValid
之前采取行动将Guid更改为实际的Invite对象吗?
从asp.net的这个tutorial建议,我应该添加一个属性来保存InviteId,而不是使用邀请对象吗?在示例中Department
未使用,所以我真的不明白它为什么被添加 - 我错过了什么?
public class Course
{
public int DepartmentID { get; set; }
public virtual Department Department { get; set; }
}
其他一些更好的方法?
答案 0 :(得分:0)
嗯,答案是在我在问题中链接的实际教程中。我需要添加一个InviteId
字段作为外键,然后实际对象充当导航属性,如下所述,两者都是必需的(不仅仅是我使用它的一个)。
Creating an Entity Framework Data Model for an ASP.NET MVC Application
StudentID属性是外键,并且对应 导航属性是学生。注册实体已关联 有一个学生实体,所以该物业只能持有一个 学生实体(与Student.Enrollments导航属性不同) 之前看到,它可以容纳多个Enrollment实体。)
CourseID属性是外键,并且对应 导航属性是课程。注册实体与 一个课程实体。
实体框架将属性解释为外键属性if 它被命名为(for 例如,自学生导航属性的StudentID 学生实体的主键是ID)。外键属性也可以 简单地命名(例如, CourseID,因为课程实体的主键是CourseID)。
答案 1 :(得分:0)
你不能在DropDownListFor:
中绑定像model.Invite这样的复杂组件@Html.DropDownListFor(model => model.Invite, (IEnumerable<SelectListItem>)ViewBag.Invites, String.Empty
你需要在ID中添加一个像int这样的奇异值。尝试将上面的代码替换为:
@Html.DropDownListFor(model => model.Invite.InviteID, (IEnumerable<SelectListItem>)ViewBag.Invites, String.Empty