使用单一视图模型在 MVC Razor 视图上发布多个表单
Posted
技术标签:
【中文标题】使用单一视图模型在 MVC Razor 视图上发布多个表单【英文标题】:Posting multiple forms on MVC Razor View with a Single View Model 【发布时间】:2017-01-15 13:36:44 【问题描述】:我有一个包含 5 个表单的剃刀视图。 (A、B、C、D、E)。这些表单中的每一个都有自己的 ViewModel(AViewModel、BViewModel、CViewModel、DViewModel、EViewModel)。
我创建了一个父 ProductViewModel,该页面将用作其唯一的 ViewModel。在此 ViewModel 中将包含页面上每个表单的所有其他 ViewModel(如上所列)。
ProductViewModel 的属性如下所示:
public AViewModel get; set;
public BViewModel get; set;
public CViewModel get; set;
public DViewModel get; set;
public EViewModel get; set;
我的剃刀视图如下所示:
@model MVCApp.ViewModels.ProductViewModel
@
ViewData["Title"] = "Product Detail";
<h2>Product Detail</h2>
<form asp-controller="A" asp-action="Save" data-ajax="true" data-ajax-method="POST">
<div class="form-horizontal">
<h4>Form A</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="AViewModel.Name" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="AViewModel.Name" class="form-control"/>
<span asp-validation-for="AViewModel.Name" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="AViewModel.StartDate" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="AViewModel.StartDate" class="form-control"/>
<span asp-validation-for="AViewModel.StartDate" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="AViewModel.EndDate" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="AViewModel.EndDate" class="form-control"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts
@await html.RenderPartialAsync("_ValidationScriptsPartial");
当点击 Save 按钮时,我最终进入了 A 控制器的 Save (POST) Action Method,正如我所期望的那样:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Save(AViewModel viewModel)
return Ok();
但是,我注意到 viewModel 参数的所有属性都是空的。
这是否意味着我真的必须将 ProductViewModel 对象作为我的 ViewModel 传递给所有 5 个表单的保存操作方法,其中只有范围内的 ViewModel 将被填充,其他所有内容都将为空?还是有更好的办法?
【问题讨论】:
【参考方案1】:我建议将每个表单都设为局部视图,并仅传入父模型所需的子模型
@await Html.RenderPartialAsync("AViewPartial", Model.AViewModel);
那么您在部分中的输入可以更改为
<input asp-for="AViewModel.Name" class="form-control"/>
到
<input asp-for="Name" class="form-control"/>
这应该使它被模型绑定器正确绑定,以便它被传递到您的操作中
【讨论】:
局部视图正是我需要的。谢谢!【参考方案2】:POST 方法的参数必须是ProductViewModel
。
这是因为属性在 HTML 中的命名方式:
<input asp-for="AViewModel.Name" class="form-control"/>
模型绑定器采用您的序列化表单,并看到您正在向 POST 方法发送一个名为 AViewModel.Name
的属性的值。当您的参数类型为 AViewModel
时,它什么也找不到,因为它正在寻找名称为 AViewModel
的参数类型的 子属性,然后分配 对象的Name
属性为输入值。
如果您不想将每个 POST 方法的参数设置为 ProductViewModel
,那么您有一个领先的替代方案:为您的五种不同表单创建局部视图,并从您的 ProductViewModel
中传递各个属性作为局部视图的模型。然后,这将从您的 asp-for
属性中消除 AViewModel
属性前缀。
【讨论】:
以上是关于使用单一视图模型在 MVC Razor 视图上发布多个表单的主要内容,如果未能解决你的问题,请参考以下文章
使用 MVC Razor 语法检查视图模型属性在 Javascript 中是不是具有值