MVC-binder无法在表单提交中绑定complex-viewmodel-property [英] MVC-binder fails to bind complex-viewmodel-property in form submit

查看:106
本文介绍了MVC-binder无法在表单提交中绑定complex-viewmodel-property的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Umbraco MVC to build a form four our webpage. I have a ViewModel which is actually a property to another ViewModel, and is populated using a partial-view in the razor-form below. For whatever reason, the sub-viewmodel (RequiredHealthInputData, se below) is always null after binding! The binder will successfully bind all the form values to my main viewmodel but my sub-viewmodel will remain null!

(我已经研究了许多有关复杂类型绑定的类似问题,但我相信,到目前为止,我发现的所有解决方案(前缀,重命名属性以支持路由等)都没有.

(I have research many similar questions regarding binding of complex types but I believe but none of the solutions I've found so far (prefixing, renaming my properties to support routing etc) works.

我有一个PtjInsurancePickerViewModel.cs(主视图模型),其外观如下:

I have a PtjInsurancePickerViewModel.cs (the main viewmodel) which looks as follows:

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

    public HealthDeclarationModel RequiredHealthInputData { get; set; }
}

HealthDeclarationModel也是ViewModel,并且具有以下值:

HealthDeclarationModel is a ViewModel as well and has the following values:

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

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

并且我具有以下格式的视图InsurancePicker.cshtml:

And I have the a view InsurancePicker.cshtml with the following form:

@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的属性

Note that the form consists of two partials, one which gets the PtjInsurancePickerViewModel and one which gets the HealthDeclarationModel which is a property of PtjInsurancePickerViewModel

这是我的HealthDeclarationModel的部分内容:

Here is the partial for my 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用于状态管理).也许这可能是问题的一部分?我尝试提交ID前缀为模型名称"HealthDeclarationModel .EnsurancePTNameSelect的ID") ",而不仅仅是"EnsurancePTNameSelect",但无济于事

(Note. I give the input fields in my partial special IDs (used by jquery for statemanagement). Perhaps this could be part of the issue? I've tried submitting with the Ids prefixed with the model name "HealthDeclarationModel .EnsurancePTNameSelect" instead of just "EnsurancePTNameSelect" for example, but to no avail)

submit函数导致以下方法:

The submit function leads to the follow method:

[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. 默认活页夹的结果将如下所示:

Now here's my problem. RequiredHealthInputData will always be null as the MVC binder for can't bind HealthDeclarationModel to PtjInsurancePickerViewModel. The result of the default binder will look something like this:

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

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

However, the form collection will look something like this:

    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.

Also note that EnsurancePTName which is an input that belongs to HalsodeklarationDataModel has the id EnsurancePTName and not HalsodeklarationDataModel.EnsurancePTName.

我真的不知道该如何进行甚至调试. 我只是一个定制的助手,以验证绑定确实排除了HalsodeklarationDataModel中的所有值

I have really no idea how to proceed with this or even how to debug it. I've just a customed helper to verify that the binding does indeed exclude all values from HalsodeklarationDataModel

推荐答案

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

The reason that is does not bind is because your use of @Html.Partial("../Partials/_Healthdeclaration", Model.RequiredHealthInputData) is generating form controls with name attributes that do not relate to PtjInsurancePickerViewModel, for example, it generates

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

需要放置的位置

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

一种选择是将HtmlFieldPrefix作为AdditionalViewData

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

另请参见

Refer also getting the values from a nested complex object that is passed to a partial view that include the code for a HtmlHelper extension method to make this simpler.

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

However the preferred approach is to use an EditorTemplate. Rename your partial to HealthDeclarationModel.cshtml (i.e. to match the name of the class) and move it to the /Views/Shared/EditorTemplates folder (or /Views/yourControllerName/EditorTemplates folder), and then in the view use

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

这将生成正确的name属性.

这篇关于MVC-binder无法在表单提交中绑定complex-viewmodel-property的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆