MVC-binder 无法在表单提交中绑定 complex-viewmodel-属性

MVC-binder fails to bind complex-viewmodel-property in form submit

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

(我研究过许多关于复杂类型绑定的类似问题,但我相信但 none 目前我找到的解决方案(添加前缀、重命名我的属性以支持路由等)有效。

我有一个 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" 而不是 "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 将始终为 null,因为 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

中的所有值

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

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

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

需要的地方

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

一个选项是将 HtmlFieldPrefix 作为 AdditionalViewData

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

另请参阅 ,其中包含 HtmlHelper 扩展方法的代码以简化此操作。

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

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

这将生成正确的 name 属性。