保存时的模型绑定不会返回完整的嵌套对象列表,最多只能返回一个
尝试理解EditorTemplates,这是一个目前无法运行的简单示例。模型没有返回完整的IList 对于项目,每次在我的例子中应该有2个时,它似乎返回1个对象。
当我编辑ModelA时,示例是:
- Name: Model A
List of Model Bs:
- Name: Model B1
List of Model Cs:
- Name: Model C1
- Name: Model C2
- Name: Model B2
此列表在编辑期间正确显示,但在保存时,部分信息“丢失”,在下方添加(not found)
。
- Name: Model A (in Model)
List of Model Bs:
- Name: Model B1 (in Model)
List of Model Cs:
- Name: Model C1 (in Model)
- Name: Model C2 (not found)
- Name: Model B2 (not found)
基本上,在保存时,模型不会从列表中返回任何多个对象。
类:
BaseObject:
public class BaseObject
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid Oid { get; set; }
}
ModelA,ModelB和ModelC:
public class ModelA : BaseObject
{
public string Name { get; set; }
public virtual IList<ModelB> ModelBs { get; set; }
}
public class ModelB : BaseObject
{
public string Name { get; set; }
public Guid? ModelAID { get; set; }
[ForeignKey("ModelAID")]
public virtual ModelA ModelA { get; set; }
public virtual IList<ModelC> ModelCs { get; set; }
}
public class ModelC : BaseObject
{
public string Name { get; set; }
public Guid? ModelBID { get; set; }
[ForeignKey("ModelBID")]
public virtual ModelB ModelB { get; set; }
}
ModelA的基本控制器,这里是编辑:
public ActionResult Edit(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
ModelA modelA = db.ModelAs.Find(id);
if (modelA == null)
{
return HttpNotFound();
}
return View(modelA);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ModelA modelA)
//Removed: [Bind(Include = "Oid,Name,DateCreated,DateUpdated,DateDeleted,IsDeleted")]
{
if (ModelState.IsValid) //Break point to review "modelA"
{
db.Entry(modelA).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(modelA);
}
查看:
Edit.cshtml(适用于ModelA):
@model x.Models.Nesting.ModelA
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.EditorForModel(Model)
}
Views / Shared / EditorTemplates中的视图:
ModelA.cshtml:
@model x.Models.Nesting.ModelA
<div class="form-horizontal">
<h4>ModelA</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Oid)
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ModelBs, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.ModelBs)
@* Tried the code below as well *@
@*
@for (var i = 0; i < Model.ModelBs.Count(); i++)
{
@Html.EditorFor(m => m.ModelBs[i])
}
*@
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
ModelB.cshtml:
@model x.Models.Nesting.ModelB
@using (Html.BeginForm())
{
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Oid)
@Html.HiddenFor(model => model.ModelAID)
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ModelCs, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.ModelCs)
@* Tried the code below as well *@
@*
@foreach(var item in Model.ModelCs)
{
@Html.EditorFor(x => item)
}
*@
</div>
</div>
</div>
}
ModelC.cshtml:
@model x.Models.Nesting.ModelC
@using (Html.BeginForm())
{
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Oid)
@Html.HiddenFor(model => model.ModelBID)
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
</div>
}
作为HTML中的示例(当使用@Html.EditorFor(model => model.ModelBs)
时),两个ModelB对象的绑定看起来看起来都是正确绑定的(但它只返回第一个对象):
模特B1:
<input
data-val="true" data-val-required="The Oid field is required."
id="ModelBs_f1aa613f-96f4-427f-a568-c70556ad2117__Oid"
name="ModelBs[f1aa613f-96f4-427f-a568-c70556ad2117].Oid"
type="hidden"
value="7e99950b-62c9-e711-afd4-7cb0c2b5b934">
<input
id="ModelBs_f1aa613f-96f4-427f-a568-c70556ad2117__ModelAID"
name="ModelBs[f1aa613f-96f4-427f-a568-c70556ad2117].ModelAID"
type="hidden"
value="7e99950b-62c9-e711-afd4-7cb0c2b5b935">
<input
class="form-control text-box single-line valid"
id="ModelBs_f1aa613f-96f4-427f-a568-c70556ad2117__Name"
name="ModelBs[f1aa613f-96f4-427f-a568-c70556ad2117].Name"
type="text"
value="Model B1" aria-invalid="false">
模型B2:
<input
data-val="true" data-val-required="The Oid field is required."
id="ModelBs_128318da-af85-46a5-bc0d-71361610d989__Oid"
name="ModelBs[128318da-af85-46a5-bc0d-71361610d989].Oid"
type="hidden"
value="7e99950b-62c9-e711-afd4-7cb0c2b5b936">
<input
id="ModelBs_128318da-af85-46a5-bc0d-71361610d989__ModelAID"
name="ModelBs[128318da-af85-46a5-bc0d-71361610d989].ModelAID"
type="hidden"
value="7e99950b-62c9-e711-afd4-7cb0c2b5b935">
<input
class="form-control text-box single-line valid"
id="ModelBs_128318da-af85-46a5-bc0d-71361610d989__Name"
name="ModelBs[128318da-af85-46a5-bc0d-71361610d989].Name"
type="text"
value="Model B2" aria-invalid="false">
在ModelA中使用for
循环时,循环ModelB(@for (var i = 0; i < Model.ModelBs.Count(); i++) { @Html.EditorFor(m => m.ModelBs[i]) }
),索引是数字,但仍然不返回完整的模型。
模特B1:
<input
data-val="true" data-val-required="The Oid field is required."
id="ModelBs_0__Oid" name="ModelBs[0].Oid"
type="hidden"
value="7e99950b-62c9-e711-afd4-7cb0c2b5b934">
<input
id="ModelBs_0__ModelAID"
name="ModelBs[0].ModelAID"
type="hidden"
value="7e99950b-62c9-e711-afd4-7cb0c2b5b935">
<input
class="form-control text-box single-line valid"
id="ModelBs_0__Name" name="ModelBs[0].Name"
type="text"
value="Model B1" aria-invalid="false">
模型B2:
<input
data-val="true" data-val-required="The Oid field is required."
id="ModelBs_1__Oid" name="ModelBs[1].Oid"
type="hidden"
value="7e99950b-62c9-e711-afd4-7cb0c2b5b936">
<input
id="ModelBs_1__ModelAID" name="ModelBs[1].ModelAID"
type="hidden"
value="7e99950b-62c9-e711-afd4-7cb0c2b5b935">
<input
class="form-control text-box single-line valid"
id="ModelBs_1__Name" name="ModelBs[1].Name"
type="text"
value="Model B 2" aria-invalid="false">
投递表格数据:
@Html.EditorFor(...)
POST (未更新ModelB的ModelC列表):
__RequestVerificationToken:1PfXHdYtb5eE-j6g4DWBEZiRa0trOL8UvYGKVjL0pxR1qOjQE52be7UB14VaIJRpp5UA1Iz9WXt4g_7LKixKhK7ah7Hjp6hOLmLa1m7XavI1
Oid:7e99950b-62c9-e711-afd4-7cb0c2b5b935
Name:Model A1
ModelBs.index:4a481093-9bdd-43ae-b84b-144c576ff346
ModelBs[4a481093-9bdd-43ae-b84b-144c576ff346].Oid:7e99950b-62c9-e711-afd4-7cb0c2b5b934
ModelBs[4a481093-9bdd-43ae-b84b-144c576ff346].ModelAID:7e99950b-62c9-e711-afd4-7cb0c2b5b935
ModelBs[4a481093-9bdd-43ae-b84b-144c576ff346].Name:Model B1
ModelBs[4a481093-9bdd-43ae-b84b-144c576ff346].ModelCs[0].Oid:7e99950b-62c9-e711-afd4-7cb0c2b5b936
ModelBs[4a481093-9bdd-43ae-b84b-144c576ff346].ModelCs[0].ModelBID:7e99950b-62c9-e711-afd4-7cb0c2b5b934
ModelBs[4a481093-9bdd-43ae-b84b-144c576ff346].ModelCs[0].Name:Model C 1
ModelBs.index:a1dd130d-a1f7-47ed-90a2-28055a960c9b
For
循环POST:
__RequestVerificationToken:x9hpnm-c1g0Cm9gTnSRjCFIVflziqXqiO3iFkzVpMc33gnNlBoDsvwBHMmRT38sWTCGrFSqCqzcuuBZdXLsXTgX1EbkqUSqPuAtwUrR1XXA1
Oid:7e99950b-62c9-e711-afd4-7cb0c2b5b935
Name:Model A1
ModelBs[0].Oid:7e99950b-62c9-e711-afd4-7cb0c2b5b934
ModelBs[0].ModelAID:7e99950b-62c9-e711-afd4-7cb0c2b5b935
ModelBs[0].Name:Model B1
ModelBs[0].ModelCs[0].Oid:7e99950b-62c9-e711-afd4-7cb0c2b5b936
ModelBs[0].ModelCs[0].ModelBID:7e99950b-62c9-e711-afd4-7cb0c2b5b934
ModelBs[0].ModelCs[0].Name:Model C 1
EditorFor
有两次ModelBs.index(希望这会导致一个解决方案),但不会在For
中。切断的东西&gt; (我加倍检查,我没有错过任何进一步的东西)
FireFox POST数据,看起来像0和1的索引在某种程度上起作用:
__RequestVerificationToken qlrlO7Z0_byGZYLGJ6Tbx5Fzmpd0dd6b-JPac4V-f1U-17v06OQr27dYZPh_VmRI3X4nGj7ZAOHtBdERnuZscJlNlgoHAqdeXaNQN04e2qE1
Oid 7e99950b-62c9-e711-afd4-7cb0c2b5b935
Name Model+A1
ModelBs.index […]
0 3d003e30-d350-4fb0-becd-f65207b033c4
1 be4e35c3-3fee-4c7f-9ee7-580b6e0c8169
ModelBs[3d003e30-d350-4fb0-becd-f65207b033c4].Oid 7e99950b-62c9-e711-afd4-7cb0c2b5b934
ModelBs[3d003e30-d350-4fb0-becd-f65207b033c4].ModelAID 7e99950b-62c9-e711-afd4-7cb0c2b5b935
ModelBs[3d003e30-d350-4fb0-becd-f65207b033c4].Name Model+B1
ModelBs[3d003e30-d350-4fb0-becd-f65207b033c4].ModelCs[0].Oid 7e99950b-62c9-e711-afd4-7cb0c2b5b936
ModelBs[3d003e30-d350-4fb0-becd-f65207b033c4].ModelCs[0].ModelBID 7e99950b-62c9-e711-afd4-7cb0c2b5b934
ModelBs[3d003e30-d350-4fb0-becd-f65207b033c4].ModelCs[0].Name Model+C+1
......神秘感仍在继续
答案 0 :(得分:0)
ModelB和ModelC的EditorTemplate文件(cshtml)有@using (Html.BeginForm())
{ ... }
,删除它解决了问题,允许POST包含所有信息。将BeginForm
保留在ModelA上,这是必需的。
我在查看POST信息时发现了它,它显示了第二个ModelB的(n).index,但是没有关联的数据,它下面还有一个form
标记,每个人都知道很多表单标签并不好。
更新了cshtml
ModelB.cshtml:
@model x.Models.Nesting.ModelB
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Oid)
@Html.HiddenFor(model => model.ModelAID)
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ModelCs, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.ModelCs)
@* Tried the code below as well *@
@*
@foreach(var item in Model.ModelCs)
{
@Html.EditorFor(x => item)
}
*@
</div>
</div>
</div>
ModelC.cshtml:
@model x.Models.Nesting.ModelC
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Oid)
@Html.HiddenFor(model => model.ModelBID)
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
</div>