ASP.NET Core MVC如何使用ViewModel正确编辑现有模型数据
问题原因及修复方案
1. Edit GET方法需要修改的位置
你在构造ViewModel的时候没有给ProjectId、ClientId、SelectedMembers赋值,导致视图提交POST请求时,model.ProjectId为默认值0,这是触发新增的核心诱因之一。
修改后的GET方法代码:
public async Task<IActionResult> Edit(int? id) { if (id == null) return NotFound(); Project project = await _context.Project .Include(p => p.ProjectMembers) // 加载已关联的成员数据 .FirstOrDefaultAsync(m => m.ProjectId == id); if (project == null) return NotFound(); var members = _context.Member .Select(m => new SelectListItem { Value = m.MemberId.ToString(), Text = m.MemberName }).ToList(); var clients = _context.Client .Select(r => new SelectListItem { Value = r.ClientId.ToString(), Text = r.Name }).ToList(); CreateProjectViewModel viewmodel = new CreateProjectViewModel { // 补充赋值ProjectId、ClientId,确保POST时能拿到正确的主键 ProjectId = project.ProjectId, ClientId = project.ClientId, Name = project.Name, Budget = project.Budget, BusinessCase = project.BusinessCase, StartDate = project.StartDate, FinishDate = project.FinishDate, // 赋值已选中的成员,编辑时视图会默认勾选 SelectedMembers = project.ProjectMembers.Select(pm => pm.MemberId).ToList(), Clients = clients, Members = members }; return View(viewmodel); }
同时要确认你的Edit视图里有隐藏字段绑定ProjectId,确保提交时该值能传递到POST方法:
@Html.HiddenFor(m => m.ProjectId)
2. Edit POST方法需要修改的位置
当前POST方法存在3个核心错误:
- 错误修改了已查询到的
project.ProjectId为可能是0的model.ProjectId,EF会把主键为0的实体识别为新实体执行新增操作 - 多对多关联逻辑错误,仅做了新增操作,没有处理用户取消原有成员的场景
- 手动设置
EntityState.Modified多余,EF会自动跟踪查询出来的实体的属性变更
修改后的POST方法代码:
public IActionResult Edit(int? id, CreateProjectViewModel model) { if (id == null || id != model.ProjectId) return NotFound(); if (!ModelState.IsValid) { // 校验失败时重新加载下拉选项返回视图 model.Members = _context.Member.Select(m => new SelectListItem { Value = m.MemberId.ToString(), Text = m.MemberName }).ToList(); model.Clients = _context.Client.Select(r => new SelectListItem { Value = r.ClientId.ToString(), Text = r.Name }).ToList(); return View(model); } Project project = _context.Project .Include(p => p.ProjectMembers) // 加载已关联的成员数据 .Single(m => m.ProjectId == id); // 修复多对多关联逻辑:先删除原有所有关联,再添加新选中的关联 _context.ProjectMembers.RemoveRange(project.ProjectMembers); if (model.SelectedMembers != null) { foreach (var selectedId in model.SelectedMembers) { _context.ProjectMembers.Add(new ProjectMember { ProjectId = project.ProjectId, MemberId = selectedId, }); } } // 修复:删除错误的project.ProjectId = model.ProjectId赋值行,主键不需要修改 project.Name = model.Name; project.Budget = model.Budget; project.BusinessCase = model.BusinessCase; project.StartDate = model.StartDate; project.FinishDate = model.FinishDate; project.ClientId = model.ClientId; // 修复:删除手动设置State的代码,EF自动跟踪变更 _context.SaveChanges(); return RedirectToAction("Index"); }
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

