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)
生成的表单控件具有 name
与 PtjInsurancePickerViewModel
无关的属性,例如,它生成
<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
属性。
我正在使用 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)
生成的表单控件具有 name
与 PtjInsurancePickerViewModel
无关的属性,例如,它生成
<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
属性。