简体   繁体   中英

How do you bind a .net Core MVC form to a Parent and Child ViewModel?

This seems old fashioned to be building an MVC app; but here goes.

I've got a Parent ViewModel that contains a single field, Description , then a collection of Child ViewModels, PowerCurvePoints . There are typically 25-30 PowerCurvePoints which should be editted as a group and posted back to the server.

How would it be best to layout the cshtml template and bind this back in the controller action?

I'm fairly certain this will fail; I'll test it in a minute, but any suggestions as to how to "make it work" would be most appreciated.

<h1>Create</h1>

<h4>Power Curve</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Description" class="control-label"></label>
                <input asp-for="Description" class="form-control" />
                <span asp-validation-for="Description" class="text-danger"></span>
            </div>
            
            @for (var i = 0; i < Model.PowerCurvePoints.Count; i++)
            {
                <div class="form-group">
                    <label asp-for="PowerCurvePoints[i].Bin" class="control-label"></label>
                    <input asp-for="PowerCurvePoints[i].Bin" class="form-control" />
                    <span asp-validation-for="PowerCurvePoints[i].Bin" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="PowerCurvePoints[i].WindSpeed" class="control-label"></label>
                    <input asp-for="PowerCurvePoints[i].WindSpeed" class="form-control" />
                    <span asp-validation-for="PowerCurvePoints[i].WindSpeed" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="PowerCurvePoints[i].ActivePower" class="control-label"></label>
                    <input asp-for="PowerCurvePoints[i].ActivePower" class="form-control" />
                    <span asp-validation-for="PowerCurvePoints[i].ActivePower" class="text-danger"></span>
                </div>
            }
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

Yes it works. The equivalent binding in the Controller method is:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Description,PowerCurvePoints")] WarrantedPowerCurveViewModel viewModel)
{
    ...
}

which populates the PowerCurvePoints child collection on ViewModel.

The amended.cshtml below lays out the child collection as a grid for editing.

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Power Curve</h4>
<hr />
<div class="row">
    <div class="col-md-12">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group col-4">
                <label asp-for="Description" class="control-label"></label>
                <input asp-for="Description" class="form-control" />
                <span asp-validation-for="Description" class="text-danger"></span>
            </div>

            @for (var i = 0; i < Model.PowerCurvePoints.Count; i++)
            {
                @if (i == 0)
                {
                    <div class="row">
                        <div class="col-4">
                            <div class="form-group">
                                <label asp-for="PowerCurvePoints[i].Bin" class="control-label"></label>
                                <input asp-for="PowerCurvePoints[i].Bin" class="form-control" readonly="readonly"/>
                                <span asp-validation-for="PowerCurvePoints[i].Bin" class="text-danger"></span>
                            </div>
                        </div>
                        <div class="col-4">
                            <div class="form-group">
                                <label asp-for="PowerCurvePoints[i].WindSpeed" class="control-label"></label>
                                <input asp-for="PowerCurvePoints[i].WindSpeed" class="form-control" readonly="readonly"/>
                                <span asp-validation-for="PowerCurvePoints[i].WindSpeed" class="text-danger"></span>
                            </div>
                        </div>
                        <div class="col-4">
                            <div class="form-group">
                                <label asp-for="PowerCurvePoints[i].ActivePower" class="control-label"></label>
                                <input asp-for="PowerCurvePoints[i].ActivePower" class="form-control" />
                                <span asp-validation-for="PowerCurvePoints[i].ActivePower" class="text-danger"></span>
                            </div>
                        </div>
                    </div>
                }
                else
                {
                    <div class="row">
                        <div class="col-4">
                            <div class="form-group">
                                <input asp-for="PowerCurvePoints[i].Bin" class="form-control" readonly="readonly"/>
                                <span asp-validation-for="PowerCurvePoints[i].Bin" class="text-danger"></span>
                            </div>
                        </div>
                        <div class="col-4">
                            <div class="form-group">
                                <input asp-for="PowerCurvePoints[i].WindSpeed" class="form-control" readonly="readonly"/>
                                <span asp-validation-for="PowerCurvePoints[i].WindSpeed" class="text-danger"></span>
                            </div>
                        </div>
                        <div class="col-4">
                            <div class="form-group">
                                <input asp-for="PowerCurvePoints[i].ActivePower" class="form-control" />
                                <span asp-validation-for="PowerCurvePoints[i].ActivePower" class="text-danger"></span>
                            </div>
                        </div>
                    </div>
                }
            }
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM