You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET一对多模型绑定失败问题排查及解决

问题描述

我正在为一对多(实际由两个一对多关系构成多对多)实体创建表单,提交时Model Binder绑定失败,提交字段无法映射到模型,原因不明。创建表单显示正常,提交数据如下:

facility.Name: TEST
facility.Code: TST
facility.RegionCode: AB
departmentFacility[0].DepartmentCode: ARR
departmentFacility[0].PrimaryRouterId: 4
departmentFacility[0].SecondaryRouterId: 1
departmentFacility[1].DepartmentCode: TFG
departmentFacility[1].PrimaryRouterId: 1
departmentFacility[1].SecondaryRouterId: 4
__RequestVerificationToken: *<removed>*
facility.Active: false
模型
public class FacilityViewModel
{
    [Required]
    public string Name { get; set; }
    [Required]
    [StringLength(3)]
    public string Code { get; set; }
    [Required]
    public Boolean Active { get; set; }
    public string RegionCode { get; set; }
    public virtual ICollection<DepartmentFacilityViewModel> DepartmentFacilities { get; set; }
}

public class DepartmentFacilityViewModel 
{
    public string DepartmentCode { get; set; }
    public int PrimaryRouterId { get; set; }
    public int SecondaryRouterId { get; set; }
}

public class FacilityDepartment
{
    public IList<DepartmentFacilityViewModel> departmentFacility { get; set; }
    public FacilityViewModel facility { get; set; }
}
视图
@using TEST.Models.FacilityViewModels
@model TEST.Models.FacilityViewModels.FacilityDepartment

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

<h1>Create</h1>

<h4>Facility</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="@Model.facility.Name" class="control-label"></label>
                <input asp-for="@Model.facility.Name" class="form-control" />
                <span asp-validation-for="@Model.facility.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.facility.Code" class="control-label"></label>
                <input asp-for="@Model.facility.Code" class="form-control" />
                <span asp-validation-for="@Model.facility.Code" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="@Model.facility.RegionCode" class="control-label"></label>
                <input asp-for="@Model.facility.RegionCode" class="form-control" />
                <span asp-validation-for="@Model.facility.RegionCode" class="text-danger"></span>
            </div>
            <div class="form-group form-check">
                <label class="form-check-label">
                    <input class="form-check-input" asp-for="@Model.facility.Active" /> @Html.DisplayNameFor(model => model.facility.Active)
                </label>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <table>
                        <thead><th>Department</th><th>Primary Router</th><th>Secondary Router</th></thead>
                        <tbody>
                        @{
                            int cnt = 0;
                            List<FacilityDepartmentData> departments = ViewBag.Departments;

                            foreach (var department in departments)
                            {
                                @:<tr><td>
                                    <input type="checkbox"
                                            name="@($"departmentFacility[{cnt}].DepartmentCode")"
                                            value="@department.DepartmentCode"
                                            class="form-check-input" 
                                            @(Html.Raw(department.Assigned ? "checked=\"checked\"" : "")) />
                                            @department.DepartmentName
                                @:</td>
                                @:<td>
                                    <select asp-for="@department.PrimaryRouterId" name="@($"departmentFacility[{cnt}].PrimaryRouterId")" id="@($"departmentFacility{cnt}_PrimaryRouterId")" class="form-control" asp-items="ViewBag.RegionRouters"><option disabled selected>--- SELECT ---</option></select>
                                @:</td>
                                @:<td>
                                    <select asp-for="@department.SecondaryRouterId" name="@($"departmentFacility[{cnt}].SecondaryRouterId")" id="@($"departmentFacility{cnt}_SecondaryRouterId")" class="form-control" asp-items="ViewBag.RegionRouters"><option disabled selected>--- SELECT ---</option></select>
                                @:</td></tr>
                                cnt++;
                                }
                        }
                        </tbody>
                    </table>
                </div>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>
控制器(原代码)
public IActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(FacilityDepartment facility)
{
    if (ModelState.IsValid)
    {
        _context.Add(facility);
        if (!ModelState.IsValid)
        {
            return View(facility);
        }
        await _context.SaveChangesAsync(User.Identity?.Name);
        return RedirectToAction(nameof(Index));
    }
    return View(facility);
}
问题解决(更新)

通过修改控制器代码解决了绑定问题,修改后的代码如下:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(FacilityDepartment facilityDepartment)
{
    if (ModelState.IsValid)
    {
        // 将facilityDepartment映射为实体类
        Facility fac = new Facility();
        fac.Name = facilityDepartment.facility.Name;
        fac.Code = facilityDepartment.facility.Code;
        fac.Active = facilityDepartment.facility.Active;
        fac.RegionCode = facilityDepartment.facility.RegionCode;
        fac.DepartmentFacilities = new List<DepartmentFacility>();

        foreach (var department in facilityDepartment.departmentFacility)
        {
            if (department is not null)
            {
                var D = new DepartmentFacility()
                {
                    PrimaryRouterId = department.PrimaryRouterId,
                    SecondaryRouterId = department.SecondaryRouterId,
                    DepartmentCode = department.DepartmentCode
                };
                fac.DepartmentFacilities.Add(D);
            }
        }

        _context.Facilities.Add(fac);
        if (!ModelState.IsValid)
        {
            return View(facilityDepartment);
        }
        await _context.SaveChangesAsync(User.Identity?.Name);
        return RedirectToAction(nameof(Index));
    }
    return View(facilityDepartment);
}

内容的提问来源于stack exchange,提问作者matthewprobasco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 16:05:03