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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 19:06:01