MVC 复杂模型与继承、嵌套视图模型和部分视图绑定
MVC Complex model binding with inheritance, nested viewModels and partial views
我无法将嵌套模型的值返回给控制器,它们都是空值。
这是简化的架构:
//The viewModel being passed to the view
public class RunnerIndexViewModel
{
public RegisterViewModel User { get; set; }
public TrainerViewModel TrainerVM { get; set; }
public RunnerBase Runner { get; set; }
[Display(Name = "AddContact", ResourceType = typeof(MyRessources))]
public bool AddContact { get; set; }
}
public class RegisterViewModel
{
// various simple type properties here
}
public class TrainerViewModel
{
// various properties here
public Unit unit { get; set; }
public List<SelectListItem> ListStatut { get; set; }
}
public abstract partial class RunnerBase
{
// entity framework class with associations
}
public class RedRunner : RunnerBase
{
// entity framework class with associations
}
public class BlueRunner : RunnerBase
{
// entity framework class with associations
}
这是从控制器接收模型的主视图(简化):
@model Web.Models.Fournisseurs.FournisseurIndexViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.Partial("PartialTrainer", Model.TrainerVM)
@Html.Partial("PartialRunner", Model.Runner as RedRunner)
@Html.Partial("PartialUser", Model.User)
}
视图 PartialTrainer 和 PartialUser 没有什么特别之处,所以这里是从 entity framework 中获取基础 class 的 PartialRunner 视图:
@model RunnerBase
@* Show Various fields from RunnerBase ... *@
@if (Model is RedRunner)
{
@* show properties specific to RedRunner *@
}
else if (Model is BlueRunner)
{
@* show properties specific to BlueRunner *@
}
我从控制器将 RedRunner 或 BlueRunner 传递给 Runner 属性。所有 viewModel 的所有字段都显示良好,但在提交表单时,我只能设法获取 AddContact 值...
如何获取我的其他视图模型和来自 Runner 的视图模型的值class?
问题出在使用局部变量上。每次进入局部时,模型上下文都会发生变化,因此 Razor 为您生成的输入不会考虑完整的 属性 路径。例如,如果您要在主视图中执行以下操作:
@Html.EditorFor(m => m.TrainerVM.SomeProperty)
结果 HTML 类似于:
<input type="text" name="TrainerVM.SomeProperty" />
但是,当使用部分时,您的助手将被称为:
@Html.EditorFor(m => m.SomeProperty)
结果 HTML 类似于:
<input type="text" name="SomeProperty" />
一旦回发,模型绑定器就不知道 SomeProperty
属于 TrainerVM
实例,因此它无法确定将发布的值绑定到哪里,您最终得到空值。要继续使用部分但回避这个问题,您需要为 ViewData.TemplateInfo.HtmlFieldPrefix
传递一个值(用于正确地为部分中所有字段的名称添加前缀):
@Html.Partial("PartialTrainer", Model.TrainerVM, new ViewDataDictionary(ViewData)
{
TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "TrainerVM" }
})
我无法将嵌套模型的值返回给控制器,它们都是空值。
这是简化的架构:
//The viewModel being passed to the view
public class RunnerIndexViewModel
{
public RegisterViewModel User { get; set; }
public TrainerViewModel TrainerVM { get; set; }
public RunnerBase Runner { get; set; }
[Display(Name = "AddContact", ResourceType = typeof(MyRessources))]
public bool AddContact { get; set; }
}
public class RegisterViewModel
{
// various simple type properties here
}
public class TrainerViewModel
{
// various properties here
public Unit unit { get; set; }
public List<SelectListItem> ListStatut { get; set; }
}
public abstract partial class RunnerBase
{
// entity framework class with associations
}
public class RedRunner : RunnerBase
{
// entity framework class with associations
}
public class BlueRunner : RunnerBase
{
// entity framework class with associations
}
这是从控制器接收模型的主视图(简化):
@model Web.Models.Fournisseurs.FournisseurIndexViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.Partial("PartialTrainer", Model.TrainerVM)
@Html.Partial("PartialRunner", Model.Runner as RedRunner)
@Html.Partial("PartialUser", Model.User)
}
视图 PartialTrainer 和 PartialUser 没有什么特别之处,所以这里是从 entity framework 中获取基础 class 的 PartialRunner 视图:
@model RunnerBase
@* Show Various fields from RunnerBase ... *@
@if (Model is RedRunner)
{
@* show properties specific to RedRunner *@
}
else if (Model is BlueRunner)
{
@* show properties specific to BlueRunner *@
}
我从控制器将 RedRunner 或 BlueRunner 传递给 Runner 属性。所有 viewModel 的所有字段都显示良好,但在提交表单时,我只能设法获取 AddContact 值...
如何获取我的其他视图模型和来自 Runner 的视图模型的值class?
问题出在使用局部变量上。每次进入局部时,模型上下文都会发生变化,因此 Razor 为您生成的输入不会考虑完整的 属性 路径。例如,如果您要在主视图中执行以下操作:
@Html.EditorFor(m => m.TrainerVM.SomeProperty)
结果 HTML 类似于:
<input type="text" name="TrainerVM.SomeProperty" />
但是,当使用部分时,您的助手将被称为:
@Html.EditorFor(m => m.SomeProperty)
结果 HTML 类似于:
<input type="text" name="SomeProperty" />
一旦回发,模型绑定器就不知道 SomeProperty
属于 TrainerVM
实例,因此它无法确定将发布的值绑定到哪里,您最终得到空值。要继续使用部分但回避这个问题,您需要为 ViewData.TemplateInfo.HtmlFieldPrefix
传递一个值(用于正确地为部分中所有字段的名称添加前缀):
@Html.Partial("PartialTrainer", Model.TrainerVM, new ViewDataDictionary(ViewData)
{
TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "TrainerVM" }
})