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

ASP.NET中HttpPost接收Subjects列表为空的问题求助

ASP.NET MVC 表单提交时列表绑定失效问题

在[HttpGet]方法中可正常获取Subjects列表,但提交请求到[HttpPost]方法时,该列表的Count始终为0。已尝试改用for循环替代foreach、添加@Html.HiddenFor(x => Model.Subjects[i].Name),还加入了<input type="hidden" asp-for="Subjects" />,目前列表不再为null但Count仍为0。需求是让Post请求时保留Get阶段的列表信息,仅更新TeacherId字段。


Controller 代码

namespace Better_Shkolo.Controllers
{
        [HttpGet]
        public IActionResult Delete(int id)
        {
            var teacher = teacherService.GetTeacher(id);
            var grade = gradeService.GetGradeByTeacherId(teacher.Id);
            var subjects = subjectService.GetSubjectsByTeacherId(teacher.Id);

            if (grade == null && subjects == null)
            {
                var result = teacherService.DeleteTeacher(id);

                if (!result)
                {
                    return BadRequest();
                }

                return RedirectToAction("Index", "Home");
            }

            var model = new GradeDeleteModel()
            {
                GradeName = grade.GradeName,
                GradeSpecialty = grade.GradeSpecialty,
                SchoolId = grade.SchoolId,
                Teachers = teacherService.GetAllTeacherInSchool(teacher.SchoolId).Where(x => x.Id != teacher.Id).ToList(),
                Subjects = subjects,
                OldTeacherId = teacher.Id,
            };

            return View(model);
        }
        [HttpPost]
        public async Task<IActionResult> Delete(GradeDeleteModel model)
        {
            var subjects = model.Subjects;

            foreach (var item in subjects)
            {
                var subject = context.Subjects.FirstOrDefault(x => x.Id == item.Id);
                subject.TeacherId = item.TeacherId;
                await context.SaveChangesAsync();
            }
            ...
        }
    }
}

View 代码

@using Better_Shkolo.Models.Grade;
@model GradeDeleteModel

<h3 class="text-center">@ViewData["Title"]</h3>
<div class="row">
    <div class="col-md-4 offset-md-4">
        <section>
            <form id="account" method="post">
                ...
                @for(int i = 0; i < Model.Subjects.Count; i++)
                {
                    <p class="list-group-item list-group-item-action">
                        @Html.DisplayFor(x => Model.Subjects[i].Name);
                        @Html.HiddenFor(x => Model.Subjects[i].Name)
                        <div class="form-group">
                            <label asp-for="@Model.Subjects[i].TeacherId"></label>
                            <select asp-for="@Model.Subjects[i].TeacherId" class="form-control">
                                @foreach (var teacher in Model.Teachers.Where(x => x.Id != Model.OldTeacherId))
                                {
                                    <option value="@teacher.Id">@teacher.FirstName @teacher.LastName - @teacher.Email</option>
                                }
                            </select>
                        </div>
                    </p>
                }

                ...
                <input type="hidden" asp-for="Subjects" />
                <div class="form-group">
                    <button type="submit" class="btn btn-primary">Delete</button>
                </div>
            </form>
        </section>
    </div>
</div>

问题原因及解决方法

核心问题

ASP.NET MVC的模型绑定需要集合项的索引+唯一标识字段才能正确识别并绑定列表。当前View中缺少Subject的Id隐藏字段,且多余的<input type="hidden" asp-for="Subjects" />会干扰绑定逻辑,导致模型绑定器无法正确解析列表项。

具体修改步骤

  1. 移除干扰字段:删除<input type="hidden" asp-for="Subjects" />,该字段会生成空集合标识,破坏正常的列表绑定规则。

  2. 添加唯一标识隐藏字段:在for循环中加入@Html.HiddenFor(x => Model.Subjects[i].Id),模型绑定需要通过Id来识别每个Subject对象,同时确保Post时能获取到每个Subject的唯一标识,用于后续数据库更新。

修改后的View循环代码:

@for(int i = 0; i < Model.Subjects.Count; i++)
{
    <p class="list-group-item list-group-item-action">
        @Html.DisplayFor(x => Model.Subjects[i].Name);
        @Html.HiddenFor(x => Model.Subjects[i].Id) <!-- 新增Id隐藏字段 -->
        @Html.HiddenFor(x => Model.Subjects[i].Name)
        <div class="form-group">
            <label asp-for="@Model.Subjects[i].TeacherId"></label>
            <select asp-for="@Model.Subjects[i].TeacherId" class="form-control">
                @foreach (var teacher in Model.Teachers.Where(x => x.Id != Model.OldTeacherId))
                {
                    <option value="@teacher.Id">@teacher.FirstName @teacher.LastName - @teacher.Email</option>
                }
            </select>
        </div>
    </p>
}
  1. 验证模型属性:确保GradeDeleteModel中的Subjects属性为List<Subject>(或对应实体类型),且Subject类的Id、Name、TeacherId均为带getter和setter的公共属性。

额外优化

  • 若仅需Id和TeacherId完成数据库更新,可移除Name的隐藏字段,减少表单提交数据量。
  • 在Post方法中添加模型验证:
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:35:30