MVC4 - 提交期间的部分视图模型绑定

时间:2013-12-19 23:28:29

标签: asp.net-mvc-4

我有一个视图模型,它有另一个子模型来渲染局部视图(下图)。

public class ExamResultsFormViewModel
{
    public PreliminaryInformationViewModel PreliminaryInformation { get; set; }

    public string MemberID { get; set; }

    public string MemberName { get; set; }

    public int PatientID { get; set; }

    public string ConfirmationID { get; set; }

    public bool IsEditable { get; set; }

    #region Select Lists
    public SelectList ProviderOptions { get; set; }
    #endregion
}

public class PreliminaryInformationViewModel
{
    public string ProviderName { get; set; }

    public string ProviderID { get; set; }

    public string ServiceLocation { get; set; }
}

此InitialInformationViewModel视图模型还用作另一个视图模型中的子模型,因为此初步信息可以在不同页面更新。

因此,我将此初步信息创建为单独的部分,并包含在其他页面中。

@{Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);}

在部分内部

@model Web.Models.Preliminary.PreliminaryInformationViewModel
<div>
    @Html.TextBoxFor(x => x.DateOfService })
</div>

但问题是在提交期间,由于HTML名称属性始终呈现为原因,因此初步模型始终为null

但是当我将父模型传递给部分时,如下所示。

@model Web.Models.Exam.ExamResultsFormViewModel
<div>
    @Html.TextBoxFor(x => x.PreliminaryInformation.DateOfService })
</div>

现在HTML元素生成为

<input type = 'text' name='PreliminaryInformation.DateOfService.DateOfService' id='PreliminaryInformation.DateOfService'>

并且在提交期间它会正确绑定。

我理解MVC根据name属性值绑定元素值,但第二个实现需要我为每个页面创建一个多部分,我不喜欢。

到目前为止,我找不到使用第一个实现的解决方案,是否可以在第一次实现提交期间使初步信息模型值绑定。

7 个答案:

答案 0 :(得分:34)

我知道它有点晚了,但它可能对某人有帮助

如果您有复杂的模型,您仍然可以使用以下方法将其传递给部分:

@Html.Partial("_YourPartialName", Model.Contact, new ViewDataDictionary()
{
    TemplateInfo = new TemplateInfo()
    {
        HtmlFieldPrefix = "Contact"
    }
})

我已经定义了带有属性的模型&#34;联系&#34;。现在HtmlFieldPrefix做的是为每个模型添加属性绑定&#34;因此模型绑定器可以找到父模型&#34;

有关于它的博文:http://www.cpodesign.com/blog/bind-partial-view-model-binding-during-submit/

.NET Core 2绑定

在.NET Core 2和MVC中,上面的答案不起作用,该属性不再可设置。

解决方案如何非常相似。

 @{ Html.ViewData.TemplateInfo.HtmlFieldPrefix = "Contact"; }
 @await Html.PartialAsync("_YourPartialName", Model.Contact)

在您提交模型后,它将再次绑定。

希望有所帮助

答案 1 :(得分:6)

您需要为PreliminaryInformationViewModel创建一个编辑器模板来替换部分视图,然后使用Html.EditorFor( m => m.PreliminaryInformation )进行调用。参考this solution。创建模板应该像将部分视图移动到Views / Shared / EditorTemplates目录一样简单。 Html.EditorFor(...)会根据您作为模型传入的类型自动使用此模板(在本例中为PreliminaryInformationViewModel

答案 2 :(得分:5)

您可以将HtmlFieldPrefix添加到局部视图的顶部:

i

这与@cpoDesign描述的方法相同,但这意味着如果需要,可以在部分视图中保留前缀。

答案 3 :(得分:3)

我也遇到了这个问题。我将使用您的代码解释我的解决方案。我从这开始:

@{
   Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);
}

对应于http帖子的操作正在寻找父模型。 http帖子正确地提交了表单,但是在子部分中没有对父部分的引用。来自子部分的提交值被忽略,相应的子属性保持为空。

我创建了一个接口IPreliminaryInfoCapable,其中包含子类型的定义,如下所示:

public interface IPreliminaryInfoCapable
{
    PreliminaryInformationViewModel PreliminaryInformation { get; set; }
}

我让我的父模型实现了这个接口。我的局部视图然后使用顶部的界面作为模型:

@model IPreliminaryInfoCapable

最后,我的父视图可以使用以下代码将自身传递给子部分:

@{
    Html.RenderPartial("ChildPartial", Model);
}

然后子部分可以使用子对象,如下所示:

@model IPreliminaryInfoCapable
...
@Html.LabelFor(m => m.PreliminaryInformation.ProviderName)
etc.

所有这些都可以在http发布时正确地填充父模型到相应的操作。

答案 4 :(得分:0)

快速提示:调用EditorFor方法时,可以将模板名称设置为Html.EditorFor方法的参数。或者,命名约定可以是你的朋友;只需确保您的编辑器模板文件名与模型属性类型

完全相同

即。 model属性类型'CustomerViewModel'=&gt; 'CustomerViewModel.cshtml'编辑模板。

答案 5 :(得分:0)

请对您的部分页面进行以下更改。所以它将伴随您的父模型

//Parent Page
@{Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);}

//Partial Page
@model Web.Models.Preliminary.PreliminaryInformationViewModel
@using (Html.BeginCollectionItem("PreliminaryInformation", item.RowId, true))
    {
<div>
@Html.TextBoxFor(x => x.DateOfService })
</div>

}

答案 6 :(得分:0)

对于.net core 2和mvc,请使用如下操作:

{this.state.isLoggedIn ?
    (
      <Route
        path='/home'
        render={() => <HomePage  onLogout={this.onLogout} />}
      />
    )
    :
    (
      <Route exact path='/' component={() => <LoginPage onLogin={this.onLogin} />}/>
    )
}