DropDownListFor设置导航属性时“值无效”

时间:2013-11-17 22:43:20

标签: asp.net entity-framework razor drop-down-menu asp.net-mvc-5

我正在尝试根据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时会出现问题。

enter image description here

创建的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);
    }

我在这里挖了一下这个原因,我想我理解了潜在的问题。我的函数PopulateInviteInviteId放入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; }
}

其他一些更好的方法?

2 个答案:

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