【问题标题】:MVC-binder fails to bind complex-viewmodel-property in form submitMVC-binder 无法在表单提交中绑定 complex-viewmodel-property
【发布时间】:2016-10-05 09:42:57
【问题描述】:

我正在使用 Umbraco MVC 来构建我们网页的表格 4。 我有一个 ViewModel,它实际上是另一个 ViewModel 的属性,并使用下面剃刀形式的部分视图填充。无论出于何种原因,绑定后的子视图模型(RequiredHealthInputData,见下文)始终为空!绑定器将成功地将所有表单值绑定到我的主视图模型,但我的子视图模型将保持为空!

(我研究了许多关于复杂类型绑定的类似问题,但我相信,但到目前为止我发现的解决方案(前缀、重命名我的属性以支持路由等)都不起作用。

我有一个 PtjInsurancePickerViewModel.cs(主视图模型),如下所示:

public class PtjInsurancePickerViewModel : BaseViewModel, IValidatableObject
{
    [Required]
    public string InsuranceNameStr { get; set; } = "-1";

    public HealthDeclarationModel RequiredHealthInputData { get; set; }
}

HealthDeclarationModel 也是一个 ViewModel,具有以下值:

public class HealthDeclarationModel : BaseViewModel, IValidatableObject
{
    [Display(Name = "Extra comment")]
    public string ExtraComments { get; set; }

    [Display(Name = "EnsurancePTName")]
    public string EnsurancePTName { get; set; }
}

我有一个视图 InsurancePicker.cshtml,格式如下:

@using (Html.BeginUmbracoForm<InsurancePickerSurfaceController>("ProcessSelections"))
{
    <h3>Select insurance</h3>
    @Html.Partial("../Partials/InsurancePicker/_vsFamilyInsuranceProtection", Model)

    <h3>Select extra options</h3>
    @Html.Partial("../Partials/_Healthdeclaration", Model.RequiredHealthInputData)

    <h3>Send!</h3>
    <input type="submit" class="btn btn-success" value="Send!" title="Confirm choices"/>
}

请注意,表单由两个部分组成,一个获取 PtjInsurancePickerViewModel,另一个获取 HealthDeclarationModel,它是 PtjInsurancePickerViewModel 的属性

这是我的 HealthDeclarationModel 的部分内容:

        <div class="HealthDeclarationModel-Panel">

            <strong>2. Är du fullt arbetsför?</strong>
            @Html.DropDownListFor(x => x.EnsurancePTName, Model.YesNoLista, new { @class = "form-control", @id = "EnsurancePTNameSelect" })
            @Html.ValidationMessageFor(x => x.EnsurancePTName)


            @Html.TextAreaFor(x => x.ExtraComments, new { @class = "form-control", style = "max-width:100%; min-width: 100%;" })
            @Html.ValidationMessageFor(x => x.ExtraComments)

        </div>

(注意。我在我的部分特殊 ID 中提供输入字段(由 jquery 用于状态管理)。也许这可能是问题的一部分?我尝试使用前缀为模型名称“HealthDeclarationModel .EnsurancePTNameSelect”的 ID 提交” 而不仅仅是“EnsurancePTNameSelect”,但无济于事)

提交函数导致如下方法:

[Authorize(Roles = "Forsakrad")]
public class InsurancePickerSurfaceController : BaseSurfaceController
{

    [HttpPost]
    public ActionResult ProcessSelections(PtjInsurancePickerViewModel filledModel)
    {
        //Checks if the very important RequiredHealthInputData submodel is null

        if (filledModel.RequiredHealthInputData == null)
        {
            throw new ApplicationException("Critical data missing!!");
        }
        else
        {
            DoImportantStuffWithRequiredHealthInputData(filledModel.RequiredHealthInputData)
        }

        return CurrentUmbracoPage();
    }
}

现在这是我的问题。 RequiredHealthInputData 将始终为空,因为 MVC 绑定器无法将 HealthDeclarationModel 绑定到 PtjInsurancePickerViewModel。 默认活页夹的结果如下所示:

    {IndividWebb.Models.PtjInsurancePickerViewModel}
       InsuranceNameStr: "0"
       HalsodeklarationDataModel: null

但是,表单集合看起来像这样:

    controllerContext.HttpContext.Request.Form.AllKeys
    {string[17]}
       [2]: "InsuranceNameStr"
       [9]: "EnsurancePTName"
       [12]: "ExtraComments"
        14]: "HalsodeklarationDataModel"

    (Some results have been excluded)

另请注意,属于 HalsodeklarationDataModel 的输入 EnsurancePTName 具有 id EnsurancePTName 而不是 HalsodeklarationDataModel.EnsurancePTName。

我真的不知道如何进行此操作,甚至不知道如何调试它。 我只是一个自定义助手来验证绑定确实排除了 HalsodeklarationDataModel 中的所有值

【问题讨论】:

  • 除非您传递 HtmlFieldPrefix(请参阅 this answer),否则您不能使用部分。您应该为 typeof HealthDeclarationModel 使用自定义 EditorTemplate ,它确实为模型绑定生成正确的 name 属性(并注意 id 属性与它无关 - 它们供 javascript/css 选择器使用)
  • 要使其成为EditorTemplate,请将您的部分重命名为HealthDeclarationModel.cshtml 并将其移动到/Views/Shared/EditorTemplates 文件夹中,然后使用@Html.EditorFor(m =&gt; m.RequiredHealthInputData)
  • 这产生了一个奇怪的结果,我的部分视图正常显示,但现在我的所有控件也打印为我的 html 中的编辑器字段,没有样式。我该如何防止这种情况?我用输入的新代码更新了上面的问题。
  • 如果您使用@Html.EditorFor(m =&gt; m.RequiredHalsoInputData),您需要正确命名文件并将其放置在正确的文件夹中(请参阅之前的评论-/Views/Shared/EditorTemplates/HealthDeclarationModel.cshtm)以及它的一个或另一个,而不是两者。如果你使用部分选项,那么前缀是"RequiredHealthInputData",而不是"HalsodeklarationModel"

标签: c# asp.net-mvc razor model-binding


【解决方案1】:

不绑定的原因是因为您使用@Html.Partial("../Partials/_Healthdeclaration", Model.RequiredHealthInputData) 正在生成具有与PtjInsurancePickerViewModel 无关的name 属性的表单控件,例如,它会生成

<textarea name="ExtraComments" ....>

需要的地方

<textarea name="RequiredHealthInputData.ExtraComments" ....>

一种选择是将HtmlFieldPrefix 传递给部分AdditionalViewData

@Html.Partial("../Partials/_Healthdeclaration", Model.RequiredHealthInputData, 
new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "RequiredHealthInputData" }})

另请参阅 getting the values from a nested complex object that is passed to a partial view,其中包含 HtmlHelper 扩展方法的代码以简化此操作。

但首选方法是使用EditorTemplate。将你的部分重命名为HealthDeclarationModel.cshtml(即匹配类的名称)并将其移动到/Views/Shared/EditorTemplates文件夹(或/Views/yourControllerName/EditorTemplates文件夹),然后在视图中使用

@Html.EditorFor(m => m.RequiredHealthInputData)

这将生成正确的name 属性。

【讨论】:

    【解决方案2】:

    更改您的 _Healthdeclaration 视图,使其使用 PtjInsurancePickerViewModel 作为视图模型。简而言之,将相同的模型传递给所有部分以确保正确的输入名称。

    【讨论】:

    • 我可以试试这个,但使用单独的 Healthdeclaration 模型的目的是能够在网络的其他部分重用它。
    • 好的,也许使用 EditorTemplate 作为 HealthDeclarationModel (growingwiththeweb.com/2012/12/…)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    相关资源
    最近更新 更多