【发布时间】:2019-05-23 15:23:27
【问题描述】:
情况:我有一个由部分组成的 ASP.NET Razor 页面。
其中一些在循环中迭代作为主页视图模型成员的集合。这些迭代的部分使用集合的成员类型作为它们自己的视图模型。
所以 Razor 的主页看起来像这样:
@model MyProject.MainViewModel
@*Other stuff...*@
@foreach (Subtype v in Model.SubViewModel)
{
Html.RenderPartial("MyPartial", v);
}
部分看起来像这样:
@model Subtype
@Html.HiddenFor(t=>t.ParentViewModelID)
@Html.EditorFor(t=>t.Field1)
@Html.EditorFor(t=>t.Field2)
这一切都适用于初始页面加载,但我想知道我应该如何处理通过 AJAX 动态添加这些部分。
假设用户按下一个按钮,该按钮最终旨在添加到这些视图模型集合之一。我可以 AJAX 回到服务器,在那里渲染适当的部分,然后返回给客户端:
[System.Web.Mvc.HttpGet]
public ActionResult AddSubtype(int mainViewModelId)
{
var model = new Sub { ParentViewModelID=mainViewModelId};
return PartialView("MyPartial", model);
}
然后我使用一些脚本将其粘贴到它所属的 DOM 中:
success: (data) => { $('#subtypeHanger').append(data);},
这似乎可行,除了一个很大的部分:当我最终提交表单时,我没有在我的视图模型中看到与这个动态添加的部分相关的数据。
我一直在尝试对此进行调试,但我想从广义上讲这是否可能 - 或者说,有多少 MVC 应该对这些东西进行抽象。显然我可以用 JavaScript 来强制它工作。不过,有没有我应该模仿的 ASP.NET MVC 模式?
编辑:我会提到一些我在发布后尝试过的事情:
手动管理局部视图的编辑控件的“名称”和“ID”属性,这样它们最终看起来就像我将这些控件嵌套在主视图中而不是局部(即更长,包含更多文本和索引)。
对局部视图使用主视图模型类。这使我将循环移动到部分中。 “name”和“id”属性看起来就像我在上面的 #1 中想要的那样,但是这种设计极大地复杂化了从我的 AJAX 调用返回部分的过程。
使用“for”循环而不是“foreach”。就其本身而言,这并不能达到我想要的效果。
综上所述,如果 #1 或 #2 是我正在做的最好的模式,也许我可以做到这一点。
【问题讨论】:
-
动态添加的表单字段(t.Field1 等)的
name属性是什么。这就是模型绑定器用于在发布/提交时将数据绑定到您的视图模型的内容。看起来Model.SubViewModel是一个列表,因此当它们被添加到循环中时,它们可能具有列表索引位置(即name="SubViewModel[0]_Field1"),但是当您动态添加时,由于它不在列表中,因此呈现如下:@987654328 @ 所以当你提交时它没有正确映射 -
@zgood 谢谢,这是 100% 正确的:名称字段是简单的未索引值,例如“Field1”。所以我想这就是我需要攻击的。如果我将我的“for”循环移动到部分内部,我认为这可能会有所帮助......但是我不能真正动态地添加那个部分,因为它是针对整个集合的。我还需要另一个,最内心的部分吗?我需要以某种方式自己管理“名称”吗?谢谢!!
-
您正在动态添加它们,您是否还打算通过 ajax 调用动态删除它们?如果是这样,管理列表项索引可能会很烦人(即,如果 #2 被删除,则在 3 个列表中,则需要
SubViewModel[2]_Field1来SubViewModel[1]_Field1才能正确绑定)。通常我发现这样做的最佳方法是创建一个循环通过inputs的javascript 函数,并确保name属性正确-具有正确的列表名称前缀(即SubViewModel)并且索引正确。然后在每个 ajax 添加和删除操作后调用该函数 -
好的@zgood,这很有帮助。谢谢。
-
重要的是要意识到,当您提交 ajax 调用时,因为 mvc 是无状态的,因此 mvc 在此之前不知道服务器上的状态更改,因此 mvc 将无法返回正确的值对于名称属性
标签: asp.net-mvc