如何填充CreateGroupViewModel?提交后ViewModel值为null问题解决
ASP.NET Core 提交时CreateGroupViewModel属性为null的解决方法
问题根源
- 页面存在两个独立的
<form>标签,订阅日期输入框在第一个表单,提交按钮在第二个表单,导致订阅日期数据无法随提交请求发送 - 使用
foreach遍历Department.Persons,生成的表单控件缺少索引标识,ASP.NET Core模型绑定无法识别集合元素 DayGroup对象仅在第一个表单中初始化,但未包含在提交的表单内,无法被绑定- 复杂对象(如
AppUser、Department)没有对应的表单字段,模型绑定无法自动填充完整对象(仅能绑定简单类型或带索引的集合)
解决方案
1. 合并表单,统一提交范围
将所有需要提交的输入控件放到同一个<form>内,确保提交时能携带所有数据:
修改后的Create.cshtml:
@using QLAnCaWeb.ViewModels @model CreateGroupViewModel <div class="container mb-3"> <div class="row pt-4"> <div class="col-6"> <h2 class="text-primary"> ĐĂNG KÝ ĂN CA CHO TẬP THỂ </h2> <h3> HỌ TÊN: @Model.AppUser.Name </h3> <h3> PHÒNG BAN: @Model.Department.DepartmentName </h3> </div> </div> </div> <!-- 合并为单个表单 --> <form method="post" asp-action="Create" class="row g-3"> <!-- 订阅日期输入区域 --> <div class="row g-3 align-items-center mb-3"> <div class="col-auto"> <label for="SubDate" class="col-form-label">NGÀY ĐĂNG KÝ: </label> </div> <div class="col-auto"> <input type="date" id="SubDate" asp-for="@Model.DayGroup.SubcriptionDate" class="form-control" /> <span asp-validation-for="@Model.DayGroup.SubcriptionDate" class="text-dark"></span> </div> </div> <div class="mb-3 row"> <div class="col-sm-3"> <input type="text" readonly class="form-control-plaintext" value="DS HỌ TÊN" /> </div> <div class="col"> <input type="text" readonly class="form-control-plaintext" value="CA 1" /> </div> <div class="col"> <input type="text" readonly class="form-control-plaintext" value="CA 2" /> </div> <div class="col"> <input type="text" readonly class="form-control-plaintext" value="CA 3" /> </div> </div> <!-- 用for循环代替foreach,添加索引支持集合绑定 --> @for (int i = 0; i < Model.Department.Persons.Count; i++) { <div class="row"> <div class="col"> <input type="text" readonly class="form-control-plaintext" value="@Model.Department.Persons[i].Name"> <!-- 添加隐藏字段传递Person的ID,供后端识别对应实体 --> <input type="hidden" asp-for="@Model.Department.Persons[i].Id" /> </div> <div class="col"> <input class="form-control" type="number" asp-for="@Model.Department.Persons[i].Set1" /> <span asp-validation-for="@Model.Department.Persons[i].Set1" class="text-dark"></span> </div> <div class="col"> <input class="form-control" type="number" asp-for="@Model.Department.Persons[i].Set2" /> <span asp-validation-for="@Model.Department.Persons[i].Set2" class="text-dark"></span> </div> <div class="col"> <input class="form-control" type="number" asp-for="@Model.Department.Persons[i].Set3" /> <span asp-validation-for="@Model.Department.Persons[i].Set3" class="text-dark"></span> </div> </div> } <div class="row g-3 align-items-center"> <div class="col-auto"> <button type="submit" class="btn btn-primary">Submit</button> </div> <div class="col-auto"> <a class="btn btn-danger" asp-controller="Home" asp-action="Index">Cancel</a> </div> </div> </form>
2. 提前初始化ViewModel中的DayGroup
在GET方法中提前初始化DayGroup,避免在视图中手动创建:
[HttpGet] public async Task<IActionResult> Create() { var userId = _contextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); var appUser = await _appUserRepository.GetByIdAsync(userId); var department = await _groupRepository.GetDepartmentByUserAsync(appUser); var createGroupViewModel = new CreateGroupViewModel() { AppUserId = userId, AppUser = appUser, Department = department, DayGroup = new DayGroup() // 提前初始化DayGroup }; createGroupViewModel.Department.Persons = await _groupRepository.GetPeopleByDepartmentAsync(department); return View(createGroupViewModel); }
3. 优化POST方法逻辑
复杂对象(如AppUser、Department)不要依赖表单绑定,而是通过ID从数据库重新获取,仅处理表单提交的可编辑数据:
[HttpPost] public async Task<IActionResult> Create(CreateGroupViewModel model) { if (!ModelState.IsValid) { // 验证失败时重新加载基础数据并返回视图 model.AppUserId = _contextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); model.AppUser = await _appUserRepository.GetByIdAsync(model.AppUserId); model.Department = await _groupRepository.GetDepartmentByUserAsync(model.AppUser); model.Department.Persons = await _groupRepository.GetPeopleByDepartmentAsync(model.Department); return View(model); } // 处理绑定成功的数据:model.DayGroup.SubcriptionDate 和 model.Department.Persons的Set字段已填充 model.AppUserId = _contextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); model.AppUser = await _appUserRepository.GetByIdAsync(model.AppUserId); model.Department = await _groupRepository.GetDepartmentByUserAsync(model.AppUser); // 后续业务逻辑 return RedirectToAction(nameof(Index)); }
4. 验证绑定效果
在POST方法开头添加断点或日志,检查model.DayGroup.SubcriptionDate和model.Department.Persons的属性是否已正确填充。
内容的提问来源于stack exchange,提问作者Trung Đặng Đức
相关产品推荐
相关产品推荐

