首页 > 解决方案 > 通过 Ajax 重新加载部分视图:部分中的控件被重命名

问题描述

我正在遵循使用 Ajax 重新加载局部视图的标准模式。但是,当局部视图重新加载时,视图中的控件具有不同的 ID。他们失去了父模型的名称。这意味着当表单被回发时,模型绑定将不起作用。

所以在下面的示例中,当页面第一次加载时,复选框 id 是“PenguinEnclosure_IsEnoughPenguins”,但在重新加载部分后,复选框 id 是“IsEnoughPenguins”。ID 必须是“PenguinEnclosure_IsEnoughPenguins”,以便模型绑定正确地将其绑定到VM 的 PenguinEnclosure 属性。

模型:

public class ZooViewModel
{
    public string Name { get; set; }
    public PenguinEnclosureVM PenguinEnclosure { get; set; }
}

public class PenguinEnclosureVM
{
    public int PenguinCount { get; set; }

    [Display(Name = "Is that enough penguins for you?")]
    public bool IsEnoughPenguins { get; set; }
}

控制器:

public ActionResult Index()
{
    var vm = new ZooViewModel
    {
        Name = "Chester Zoo",
        PenguinEnclosure = new PenguinEnclosureVM { PenguinCount = 7 }
    };

    return View(vm);
}

public ActionResult UpdatePenguinEnclosure(int penguinFactor)
{
    return PartialView("DisplayTemplates/PenguinEnclosureVM", new PenguinEnclosureVM { PenguinCount = penguinFactor * 10 });
}

看法:

@model PartialProblem.Models.ZooViewModel

@Scripts.Render("~/bundles/jquery")

<p>
    Welcome to @Model.Name !
</p>
<p>
    <div id="penguin">
        @Html.DisplayFor(m => m.PenguinEnclosure)
    </div>
</p>

<button id="refresh">Refresh</button>

<script>
    $(document).ready(function () {
        $("#refresh").on("click", function () {
            $.ajax({
                url: "/Home/UpdatePenguinEnclosure",
                type: "GET",
                data: { penguinFactor: 42 }
            })
            .done(function (partialViewResult) {
                $("#penguin").html(partialViewResult);
            });
        });
    });
</script>

局部视图:

@model PartialProblem.Models.PenguinEnclosureVM

<p>
    We have @Model.PenguinCount penguins
</p>
<p>
    @Html.LabelFor(m => m.IsEnoughPenguins)
    @Html.CheckBoxFor(m => m.IsEnoughPenguins)
</p>

标签: ajaxasp.net-mvcpartial-views

解决方案


我使用的一种方法是在响应您的 ajax 调用 (UpdatePenguinEnclosure) 的操作中设置“ViewData.TemplateInfo.HtmlFieldPrefix”属性。这告诉 Razor 为您的控件名称和/或 Id 添加前缀。

您可以选择是否对 HtmlFieldPrefix 进行硬编码,或者将其传递给 ajax 调用中的操作。我倾向于做后者。例如,在页面上添加一个隐藏输入及其值:

<input type="hidden" id="FieldPrefix" value="@ViewData.TemplateInfo.HtmlFieldPrefix" />

在您的 ajax 调用中访问它:

            $.ajax({
                url: "/Home/UpdatePenguinEnclosure",
                type: "GET",
                data: { penguinFactor: 42, fieldPrefix: $("#FieldPrefix").val() }
            })

然后在你的行动中:

public ActionResult UpdatePenguinEnclosure(int penguinFactor, string fieldPrefix)
{
    ViewData.TemplateInfo.HtmlFieldPrefix = fieldPrefix;
    return PartialView("DisplayTemplates/PenguinEnclosureVM", new PenguinEnclosureVM { PenguinCount = penguinFactor * 10 });
}

推荐阅读