简体   繁体   English

保存时的模型绑定未返回完整的嵌套对象列表,最多一个

[英]Model Binding on Save isn't returning full List of Nested Objects, maximum of one

Model Binding on Save isn't returning full List of Nested Objects, maximum of one 保存时的模型绑定未返回完整的嵌套对象列表,最多一个

Trying to understand EditorTemplates, here is a simple example that isn't working at the moment. 试图了解EditorTemplates,这是一个目前无法使用的简单示例。 The Model isn't returning the full IList of items, it seems to be returning 1 object each time when there should be 2 in my example. 模型没有返回完整的IList项,在我的示例中每次应该有2个对象时,似乎都返回了1个对象。

When I Edit ModelA, the example is: 当我编辑ModelA时,示例为:

- Name: Model A
    List of Model Bs:
        - Name: Model B1
            List of Model Cs:
                - Name: Model C1
                - Name: Model C2
        - Name: Model B2

This list shows up properly during Edit, but upon Save, some of the information is "lost", added (not found) below. 此列表在编辑过程中正确显示,但是在保存时,某些信息“丢失”, (not found)下面添加(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)

Basically, on Save, the Model is not returning any more than one object from a list. 基本上,在保存时,模型从列表中返回的对象不超过一个。

Classes: 类:

BaseObject: BaseObject:

public class BaseObject
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public Guid Oid { get; set; }

}

ModelA, ModelB and ModelC: 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; }
}

Basic Controller for ModelA, here is the Edit: 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);
}

Views: 观看次数:

Edit.cshtml (for ModelA): Edit.cshtml(用于ModelA):

@model x.Models.Nesting.ModelA

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.EditorForModel(Model)
}

Views in Views/Shared/EditorTemplates: 视图/共享/编辑器模板中的视图:

ModelA.cshtml: 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: 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: 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>
}

As an example from the HTML (when using @Html.EditorFor(model => model.ModelBs) ), the binding for both ModelB objects look look like they would be bound properly (but it only returns the first object): 作为HTML的示例(使用@Html.EditorFor(model => model.ModelBs) ),两个ModelB对象的绑定看起来都将被正确绑定(但只返回第一个对象):

Model B1: 型号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">

Model B2: 型号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">

When using the for loop in ModelA, looping ModelB ( @for (var i = 0; i < Model.ModelBs.Count(); i++) { @Html.EditorFor(m => m.ModelBs[i]) } ), the Indexes are Numbers, but still don't return full Models. 在ModelA中使用for循环时,循环ModelB( @for (var i = 0; i < Model.ModelBs.Count(); i++) { @Html.EditorFor(m => m.ModelBs[i]) } ),索引是数字,但仍不返回完整的模型。

Model B1: 型号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">

Model B2: 型号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">

POST Form Data : POST表格数据

@Html.EditorFor(...) POST (didn't update ModelBs list of ModelCs) : @Html.EditorFor(...) POST (未更新ModelC的ModelBs列表)

__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 loop POST: 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 has ModelBs.index twice (hopeful this leads to a solution), but not in the For . EditorFor有两次ModelBs.index(希望这会导致解决方案),但是在For没有。 Something getting cut off> (I double and triple checked that I wasn't missing something further down) 某些东西被截断了>(我仔细检查了三遍,以确保我没有错过更多内容)

FireFox POST data, looks like the Indexes of 0 and 1 are working to some extent: 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

... the mystery continues ...奥秘还在继续

The EditorTemplate files (cshtml) for ModelB and ModelC had @using (Html.BeginForm()) { ... } , removing this resolved the issue, allowing the POST to contain all the information. 用于ModelB和ModelC的EditorTemplate文件(cshtml)具有@using (Html.BeginForm()) { ... } ,消除了此问题,从而允许POST包含所有信息。 Kept the BeginForm on ModelA, that is required. BeginForm保留在BeginForm上,这是必需的。

I figured it out when reviewing the POST information, it showed a(n) .index for the second ModelB, but no associated data, it also has a form tag directly below, everyone knows that many form tags isn't good. 我在查看POST信息时发现了该错误,它显示了第二个ModelB的a.n.index,但没有关联的数据,它的正下方还有一个form标签,每个人都知道很多表单标签都不好。

Updated cshtml 更新了cshtml

ModelB.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: 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM