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

.NET 6中视图循环内选中项值无法完整传递至控制器求助

解决方案

问题根源

当前视图循环生成了多个同名的表单控件(如name="EmployeeID"),但ViewModel中对应的是单个值属性,ASP.NET Core模型绑定只能捕获最后一个(或第一个)控件的值,无法收集所有行的选择结果。需要将ViewModel调整为集合结构,让表单控件生成带索引的name属性,确保模型绑定能识别所有条目。


1. 调整ViewModel结构

创建子模型存储单天的排班信息,再在主模型中添加该子模型的集合:

// 子模型:存储单条排班记录
public class EmpShiftItem
{
    public string Date { get; set; }
    public int? EmployeeID { get; set; } // 改为可空类型,避免未选择时传入默认值0
    public int? ShiftsID { get; set; }
    public string Priority { get; set; }
}

// 主视图模型
public class EmpShifts
{
    public int DepartmentID { get; set; }
    public IEnumerable<Departments>? Departments { get; set; }
    public IEnumerable<Employee>? Employees { get; set; } = new List<Employee>();
    public IEnumerable<Shifts>? Shifts { get; set; } = new List<Shifts>();
    // 移除原单个的EmployeeID、ShiftsID,改用集合存储所有排班条目
    public List<EmpShiftItem> ShiftItems { get; set; } = new List<EmpShiftItem>();
}

2. 更新控制器初始化逻辑

在GetSheduleWithEmp方法中,为ShiftItems初始化数据,确保每个日期对应一个空条目:

public async Task<IActionResult> GetSheduleWithEmp(int DepartmentId, DateTime Start, DateTime End)
{
    List<string> dates = Enumerable.Range(0, 1 + End.Subtract(Start).Days)
          .Select(i => Start.AddDays(i).ToString("dd-MM-yyyy"))
          .ToList();
              
    if (DepartmentId != 0)
    {
        var Shifts = await eRDbContext.Shifts.ToListAsync();
        var model = await eRDbContext.Employees.Where(x => x.DepartmentId == DepartmentId).ToListAsync();
        EmpShifts EmpShiftsView = new EmpShifts
        {
            DepartmentID = DepartmentId,
            Employees= model,
            Shifts = Shifts,
            // 初始化ShiftItems,每个日期对应一个空条目
            ShiftItems = dates.Select(date => new EmpShiftItem { Date = date }).ToList()
        };
        return View("AddEmployeeToShifts", EmpShiftsView);
    }
    return View();
}

3. 修改视图渲染逻辑

使用ShiftItems的索引生成表单控件,确保每个控件的name属性带索引,让模型绑定能识别所有条目:

<form asp-action="SaveShifts" class="form" method="post">
    @if (Model.ShiftItems != null && Model.ShiftItems.Any())
    {
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>Date</th>
                    <th>Employee</th>
                    <th>Shift</th>
                    <th>Priority</th>
                </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < Model.ShiftItems.Count; i++)
                {
                    <tr>
                        <td>
                            @Model.ShiftItems[i].Date
                            <!-- 隐藏域提交日期,确保后台关联对应排班 -->
                            <input type="hidden" asp-for="ShiftItems[i].Date" />
                        </td>
                        <td>
                            <select class="form-select" asp-for="ShiftItems[i].EmployeeID" asp-items="@(new SelectList(Model.Employees,"Id","Name"))">
                                <option value="">Please Select Employee</option>
                            </select>
                        </td>
                        <td>
                            <select class="form-select" asp-for="ShiftItems[i].ShiftsID" asp-items="@(new SelectList(Model.Shifts,"Id","Name"))">
                                <option value="">Please Select Shift</option>
                            </select>
                        </td>
                        <td>
                            <select class="form-select" asp-for="ShiftItems[i].Priority">
                                <option value="1st Oncall">1st Oncall</option>
                                <option value="2nd Oncall">2nd Oncall</option>
                                <option value="3rd Oncall">3rd Oncall</option>
                            </select>
                        </td>
                    </tr>
                }
            </tbody>
        </table>
        <div class="col-12">
            <button type="submit" class="btn btn-primary mx-auto">Submit</button>
        </div>
    }
</form>

4. 接收提交数据的控制器方法

在SaveShifts方法中,直接接收EmpShifts模型,此时ShiftItems集合会包含所有行的选择数据:

using System.Globalization;

[HttpPost]
public async Task<IActionResult> SaveShifts(EmpShifts model)
{
    if (!ModelState.IsValid)
    {
        // 验证失败时重新填充员工、班次列表并返回视图
        model.Employees = await eRDbContext.Employees.Where(x => x.DepartmentId == model.DepartmentID).ToListAsync();
        model.Shifts = await eRDbContext.Shifts.ToListAsync();
        return View("AddEmployeeToShifts", model);
    }

    // 遍历所有排班条目,执行保存逻辑
    foreach (var item in model.ShiftItems)
    {
        if (item.EmployeeID.HasValue && item.ShiftsID.HasValue)
        {
            // 替换为你的排班实体类
            var schedule = new Schedule
            {
                DepartmentId = model.DepartmentID,
                EmployeeId = item.EmployeeID.Value,
                ShiftId = item.ShiftsID.Value,
                Date = DateTime.ParseExact(item.Date, "dd-MM-yyyy", CultureInfo.InvariantCulture),
                Priority = item.Priority
            };
            eRDbContext.Schedules.Add(schedule);
        }
    }
    await eRDbContext.SaveChangesAsync();

    return RedirectToAction("YourSuccessAction");
}

关键说明

  • asp-for="ShiftItems[i].XXX"会自动生成带索引的name属性(如ShiftItems[0].EmployeeID),ASP.NET Core模型绑定会自动将这些值映射到集合中。
  • 子模型使用可空int?类型,避免用户未选择时传入默认值0,便于判断必填项。
  • 添加隐藏域传递日期,确保后台能准确关联每条排班记录对应的日期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:50:26