C# 通过Ajax和局部视图动态修改嵌套集合的CreateModel

C# 通过Ajax和局部视图动态修改嵌套集合的CreateModel,c#,razor-pages,partial-views,modelstate,C#,Razor Pages,Partial Views,Modelstate,我有一个非常基本的案例,我有一个解决方案,但我认为这种方式不是最干净/高效/可移植的 当然,为了便于阅读,我简化了模型,实际情况要复杂得多 型号: public partial class Referal { public Referal() { Childrens = new List<Children>(); } public int Id { get; set; } public string Name { get; s

我有一个非常基本的案例,我有一个解决方案,但我认为这种方式不是最干净/高效/可移植的

当然,为了便于阅读,我简化了模型,实际情况要复杂得多

型号:

public partial class Referal
{
    public Referal()
    {
        Childrens = new List<Children>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public List<Children> Childrens { get; set; }
}

public partial class Children
{
    public int Id { get; set; }
    public string Firstname { get; set; }
    public bool Vaccinated { get; set; }
    public int ReferalId { get; set; }
    
    public virtual Referal Referal { get; set; }

}
因此,我删除了所有名为
[Input.Childrens[index]*
的字段,然后将索引较高的字段重命名为索引小于1的字段

即使它工作得很好,即使没有数据丢失,用户可以真正安全地使用它,我也不太喜欢通过客户端脚本责任来超越输入模型机制。此外,在其他实体的其他场景中移植这段代码也不太可能

我很想知道我是否错过了一个神奇的方法,让C#在保存之前删除我的createModel的一个特定子项(因此所有输入子项都有一个id=0),而不需要这个js客户端处理


感谢您的阅读和帮助。

发布表单时,有两种方法可以绑定集合。一种是您当前正在执行的操作,即使用顺序索引,该索引从0开始,集合中的每个元素递增1

另一种方法是使用显式索引,它可以是任何不需要顺序的值。它甚至不需要是数字。这种方法需要为每个项添加一个名为
[property]的隐藏字段。index
表示该项的索引

<input type="hidden" name="Input.Children.Index" value="A" />
<input type="text" name="Input.Children[A].FirstName" />

然后,如果从集合中删除元素,则不需要对其余的元素重新编制索引


有关更多信息,请参见此:

谢谢,非常好。我没有找到HiddenFor(modelIndex),但这段代码完成了此任务:
。我想只要禁用此字段就可以清理我的数据!谢谢!
@page "{handler?}/{id?}"
@model CreateModel

<section class="extended">
<form method="post" id="souscription">

    <div class="form-group">
        <label asp-for="Input.Name" class="control-label">
        </label><input asp-for="Input.Name" class="form-control" />
    </div>

    <div id="NestedChildrens">
        @Html.EditorFor(Model => Model.Input.Childrens)
    </div>
    <button type="button" class="cgicon-register intermediary" data-nested="childrens">Add a child</button>

    <button type="submit" class="cgicon-send mainbutton">Create Now</button>

</form>
</section>
@model Models.Children

<div class="children">
<div class="form-group-header">
    Add child
    <button type="button" data-nested="childrens" data-removal="@Model.NId"></button>
</div>
<div class="form-group">
    <label asp-for="Firstname" class="control-label">
    </label><input asp-for="Firstname" class="form-control" />
</div>
<div class="form-group form-check">
    <label class="form-check-label">
        <input class="form-check-input" asp-for="Vaccinated" /> Got his fix already
    </label>
</div>
</div>
<script>
    manageChildren(document);
    function manageChildren(childContainer) {
        [].forEach.call(childContainer.querySelectorAll("button[data-nested='childrens']"), function (button, index) {
            button.addEventListener("click", function () {
                let id = "";
                if (!$(this).hasClass("cgicon-register")) {
                    var brotherHood = childContainer.querySelectorAll(".children").length;
                    if(brotherHood<=1) return false;
                    [].forEach.call(childContainer.querySelectorAll("[name^='Input.Childrens[" + index+ "]'"), function (input) {
                        input.setAttribute("disabled", "true");
                    });
                    for (i = id + 1; i < brotherHood; i++) {
                        [].forEach.call(childContainer.querySelectorAll("[name^='Input.Childrens[" + i + "]'"), function (input) {
                            input.setAttribute("name", input.getAttribute("name").replace("Input.Childrens[" + i + "]", "Input.Childrens[" + (i - 1) + "]"));
                        });
                    }
                    id = index;                         
                }
                $.ajax({
                    async: true,
                    data: $("#souscription").serialize(),
                    type: "POST",
                    url: "/Create/PartialChildren/" + id,
                    success: function (nestedList) {
                        $("#NestedChildrens").html(nestedList);
                        manageChildren(document.getElementById("NestedChildrens"));
                    }
                });
            });
        });
    }
</script>
<input type="hidden" name="Input.Children.Index" value="A" />
<input type="text" name="Input.Children[A].FirstName" />