使用单一视图模型在MVC Razor视图上发布多个表单

本文关键字:视图 布多个 表单 Razor 单一 模型 MVC | 更新日期: 2023-09-27 18:06:02

我有一个包含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");}
}

当保存按钮被点击时,我在A控制器的保存(POST)动作方法中结束,正如我所期望的:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Save(AViewModel viewModel)
    {
        return Ok();
    }

但是,我注意到viewModel参数的所有属性都是空的

这是否意味着我真的必须将ProductViewModel对象作为我的ViewModel传递给所有5个这些表单的Save Action方法,其中只有ViewModel在范围内将被填充,其他一切将为空?还是有更好的办法?

使用单一视图模型在MVC Razor视图上发布多个表单

我建议让每个表单都成为一个局部视图,并且只传递父模型所需的子模型

 @{await Html.RenderPartialAsync("AViewPartial", Model.AViewModel); }

则部分中的输入可以从

更改
<input asp-for="AViewModel.Name" class="form-control"/>

<input asp-for="Name" class="form-control"/>

会使它被模型绑定器正确地绑定,这样它就会被传递到你的动作

POST方法的参数必须为ProductViewModel

原因在于HTML中属性的命名方式:

<input asp-for="AViewModel.Name" class="form-control"/>

模型绑定器接受您的序列化表单,并看到您正在向POST方法发送一个名为AViewModel.Name的属性值。当你的参数是AViewModel类型时,它找不到任何东西,因为它正在寻找子属性你的参数类型名称为AViewModel,然后分配对象的Name属性给输入的值。

如果你不想让你的每个POST方法的参数ProductViewModel,那么你有一个主要的替代方案:为你的五个不同的表单创建部分视图,并从你的ProductViewModel传入单个属性作为部分视图的模型。这将从您的asp-for属性中消除AViewModel属性前缀。