ASP.NET MVC:动态添加部分视图并将它们反映在视图模型中

Posted

技术标签:

【中文标题】ASP.NET MVC:动态添加部分视图并将它们反映在视图模型中【英文标题】:ASP.NET MVC: Adding partial views dynamically and having them reflected in the view model 【发布时间】: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]_Field1SubViewModel[1]_Field1 才能正确绑定)。通常我发现这样做的最佳方法是创建一个循环通过inputs 的javascript 函数,并确保name 属性正确-具有正确的列表名称前缀(即SubViewModel)并且索引正确。然后在每个 ajax 添加和删除操作后调用该函数 好的@zgood,这很有帮助。谢谢。 重要的是要意识到,当您提交 ajax 调用时,因为 mvc 是无状态的,因此 mvc 在此之前不知道服务器上的状态更改,因此 mvc 将无法返回正确的值对于名称属性 【参考方案1】:

“情况:我有一个由部分组成的 ASP.NET Razor 页面。”

这称为“主详细信息”

检查 Master Details CRUD with MVC 5 | The ASP.NET Forums

诀窍是为您的字段命名

@Html.HiddenFor(t=>t.ParentViewModelID ,new  htmlAttributes = new  @Name = "[" + i + "].ParentViewModelID"  )
@Html.EditorFor(t=>t.Field1 ,new  htmlAttributes = new  @Name = "[" + i + "].Field1"  )
@Html.EditorFor(t=>t.Field2 , new  htmlAttributes = new  @Name = "[" + i + "].Field2"  )

原来如此

<input type="text" name="[0].Field1" />
<input type="text" name="[0].Field2" />
<input type="text" name="[1].Field1" />
<input type="text" name="[1].Field2" />

如果你使用更好(对于 ASP.NET mvc 5 模型绑定)

public ActionResult Edit(MainViewModel master, List<Subtype> details)

如果您提供完整模型,我将提供完整的工作示例

【讨论】:

谢谢。似乎手动管理“名称”是做到这一点的唯一方法。不过,我自己并不能完全做到这一点,所以你的例子很有帮助。确认没有一些开箱即用的魔法可以解决这个问题也很好。 @user1172763 如果您提供完整模型,我将提供完整的工作示例

以上是关于ASP.NET MVC:动态添加部分视图并将它们反映在视图模型中的主要内容,如果未能解决你的问题,请参考以下文章

从 ASP.NET MVC 操作返回部分视图和 JSON

ASP.NET MVC 最好的视图引擎是什么?

C# ASP.NET MVC:动态更新视图

在 MVC ASP.Net 中将插件添加到部分视图选择列表

如何在 ASP .NET MVC 5 中使用 select2 将新值动态添加到列表框并将其传递给控制器​​?

asp.net mvc 3 和动态视图生成