如何在编辑中绑定与父对象关联的虚拟属性集合

How can I bind virtual collection of properties associated with parent object in edit

我有两个 classes:

public class bill {

    public int billId { get;set;}

    public decimal billAmount { get;set;}

    ...................

    public virtual ICollection<lift> Lifts { get;set;}
}

public class lift {

    public int liftId { get;set;}

    public int billId { get;set;}

    ......
}

我认为我正在使用以下代码访问与现有账单相关的子付款:

                    @for (int i = 0; i < Model.Lifts.Where(x => x.archived != true).ToList().Count; i++)
                    {
                        <tr>
                            <td>@Html.EditorFor(model => model.Lifts.ToList()[i].liftId, new { htmlAttributes = new { @class = "form-control" } })</td>
                            @Html.ValidationMessageFor(model => model.Lifts.ToList()[i].liftId, "", new { @class = "text-danger" })

                            <td>@Html.EditorFor(model => model.Lifts.ToList()[i].liftDate, new { htmlAttributes = new { @class = "form-control" } })</td>
                            @Html.ValidationMessageFor(model => model.Lifts.ToList()[i].liftDate, "", new { @class = "text-danger" })

                            <td>@Html.EditorFor(model => model.Lifts.ToList()[i].liftAmount, new { htmlAttributes = new { @class = "form-control" } })</td>
                            @Html.ValidationMessageFor(model => model.Lifts.ToList()[i].liftAmount, "", new { @class = "text-danger" })

                            <td>@Html.EditorFor(model => model.Lifts.ToList()[i].archived, new { htmlAttributes = new { @class = "form-control" } })</td>
                            @Html.ValidationMessageFor(model => model.Lifts.ToList()[i].archived, "", new { @class = "text-danger" })

                            <td>@Html.EditorFor(model => model.Lifts.ToList()[i].archivedDate, new { htmlAttributes = new { @class = "form-control" } })</td>
                            @Html.ValidationMessageFor(model => model.Lifts.ToList()[i].archivedDate, "", new { @class = "text-danger" })

                        </tr>
                    }

这一切都按预期工作,包括付款的字段验证,如果我从电梯中删除必填字段 class 但是当我 post 我的模型保存更改的账单时 Model.Lifts实体总是空的

我如何才能将更改后的电梯实体从相关账单绑定到我的账单编辑控制器的 post,我尝试将 属性 附加到其他属性的列表中,但这有没用。我的控制器如下:

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "billId,.......,Lifts")] bill bill)
        {
            if (ModelState.IsValid)
            {
                db.Entry(bill).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(bill);
        }

您在 HtmlHelper 方法中使用 .ToList() 会生成 name 属性,例如 name="[0].liftId"name="[0].liftDate" 等,但为了绑定到您的模型,它们必须是 name="Lifts[0].liftId"name="Lifts[0].liftDate"(即以 属性 名称为前缀)。此外,您的验证将无法正常工作。

既然您编辑了数据,您应该使用 view model 这也将允许您在 GET 方法中过滤数据。

public class LiftVM // add validation and display attributes as required
{
    public int ID { get; set; } // no need for a hidden input if you using the default routing
    public DateTime Date { get; set; }
    .... // note that  a billId property will not be required
}

public class BillVM // add validation and display attributes as required
{
    public int ID { get; set; }
    public decimal Amount { get; set; }
    ....
    public IList<liftVM> Lifts { get; set; }
}

并在 GET 方法中,将您的数据模型映射到视图模型的实例

bill data = .... // your query to get the data model
BillVM model = new BillVM
{
    ID = data.billId,
    Amount = data.billAmount,
    ....
    Lifts = data.Lifts.Where(x => !x.archived).Select(x => new LiftVM
    {
        ID = x.liftId,
        Date = x.liftDate,
        ....
    }).ToList()
};
return View(model);

请注意,automapper 等工具可以使映射数据模型更容易查看模型。

然后在视图中

@model BillVM
....
@for (int i = 0; i < Model.Lifts.Count; i++)
{
    <tr>
        <td>
            @Html.EditorFor(m => m.Lifts[i].ID, new { htmlAttributes = new { @class = "form-control" } })
            // Note this need to be inside a <td>
            @Html.ValidationMessageFor(m => model.Lifts[i].ID, new { @class = "text-danger" })
        </td>

最后,POST 方法中的参数将为 BillVM,如果视图模型有效,则将视图模型映射回数据模型