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

ASP.NET Core中如何在局部视图回显表单错误与未完成数据?

解决方案:表单验证失败时保留输入并返回原页面

你遇到的这个问题是局部视图处理表单提交时的典型痛点——因为没有独立的CreateNote视图,验证失败后需要回到Details页面,同时还要保留用户已经输入的内容和验证错误提示。之前尝试的RedirectToAction会导致所有临时数据丢失,而视图的Model只读也限制了直接修改的可能,下面给你一套可行的解决方案:

1. 修改CreateNote控制器方法,直接返回Details视图而不是重定向

重定向(RedirectToAction)会触发新的GET请求,之前的表单数据和ModelState都会被清空,所以我们需要服务器端直接返回Details视图,把验证失败的草稿数据和错误状态一并传递过去:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateNote(int projectId, [Bind("Title,Contents")] ProjectNote note)
{
    Project project = await db.Projects
        .Include(n => n.Notes)
        .Include(p => p.ParentProject)
        .Include(c => c.ChildProjects)
        .ThenInclude(o => o.ProjectOwner)
        .Include(o => o.ProjectOwner)
        .FirstOrDefaultAsync(p => p.Id == projectId);
    
    if (project == null)
    {
        return NotFound();
    }
    
    if (project.Completed)
    {
        return RedirectToAction("Details", new { id = project.Id });
    }
    
    note.ProjectId = projectId;
    note.Created = DateTime.Now;
    
    if (ModelState.IsValid)
    {
        db.Add(note);
        await db.SaveChangesAsync();
        return RedirectToAction("Details", new { id = projectId });
    }
    
    // 验证失败:构建Details页面的ViewModel,携带草稿数据
    ProjectViewModel vm = auto.Map<ProjectViewModel>(project);
    vm.ProjectNoteAction = "c"; // 保持创建模式激活状态
    vm.DraftNote = auto.Map<ProjectNoteViewModel>(note); // 存储用户输入的草稿
    
    // 保留ModelState错误,让前端验证提示正常显示
    return View("Details", vm);
}

2. 扩展ProjectViewModel,新增草稿数据属性

在你的ProjectViewModel中添加一个属性,用来存储验证失败的笔记草稿:

public ProjectNoteViewModel DraftNote { get; set; }

3. 调整主视图Details.cshtml,传递草稿数据到局部视图

修改渲染_notes局部视图的代码,把草稿数据传递过去:

<partial name="_notes" model="@new ProjectNotesViewModel { 
    ProjectId = Model.Id, 
    Notes = Model.Notes, 
    ProjectNoteId = Model.ProjectNoteId, 
    ProjectNoteAction = Model.ProjectNoteAction, 
    ProjectCompleted = Model.Completed,
    DraftNote = Model.DraftNote // 传递草稿数据
}" />

4. 更新_notes局部视图,渲染带草稿的创建表单

在_notes.cshtml中添加创建模式的渲染逻辑,优先使用草稿数据填充表单:

@* 先渲染创建模式的表单 *@
@if (Model.ProjectNoteAction == "c")
{
    <tr class="alert-black-50">
        <td class="align-text-top text-light rounded-left" width="1">
            <span class="fas fa-clipboard fa-fw"></span>
        </td>
        <td class="pb-2 pr-2 text-light rounded-right">
            @* 如果有草稿就用草稿数据,否则用空模型 *@
            <partial name="_noteCreate" model="@(Model.DraftNote ?? new ProjectNoteViewModel { ProjectId = Model.ProjectId })" />
        </td>
    </tr>
}

@* 原有的笔记列表渲染逻辑 *@
@foreach (ProjectNoteViewModel note in Model.Notes)
{
    // 你的原有代码...
}

备选方案:用TempData实现重定向后保留数据(适合必须重定向的场景)

如果业务上必须用RedirectToAction,可以把草稿数据序列化后存入TempData(短期会话存储):

// 在CreateNote方法的验证失败分支
var draftVm = auto.Map<ProjectNoteViewModel>(note);
TempData["DraftNote"] = JsonSerializer.Serialize(draftVm);
// 同时存储ModelState错误
var errorDict = ModelState.ToDictionary(kv => kv.Key, kv => kv.Value.Errors.Select(e => e.ErrorMessage).ToList());
TempData["ModelStateErrors"] = JsonSerializer.Serialize(errorDict);

return RedirectToAction("Details", new { id = projectId, a = "c" });

然后在Details控制器方法中读取TempData并恢复数据:

public async Task<IActionResult> Details(int? id, int n, string a)
{
    // 原有的查询逻辑...
    ProjectViewModel vm = auto.Map<ProjectViewModel>(project);
    
    // 读取TempData中的草稿和错误
    if (TempData.ContainsKey("DraftNote"))
    {
        vm.DraftNote = JsonSerializer.Deserialize<ProjectNoteViewModel>(TempData["DraftNote"].ToString());
        var errors = JsonSerializer.Deserialize<Dictionary<string, List<string>>>(TempData["ModelStateErrors"].ToString());
        foreach (var error in errors)
        {
            foreach (var message in error.Value)
            {
                ModelState.AddModelError(error.Key, message);
            }
        }
    }
    
    vm.ProjectNoteAction = a;
    // ...其他赋值逻辑
    return View(vm);
}

核心原理说明

  • 直接返回Details视图:服务器端直接渲染页面,能保留ModelState错误和草稿数据,不需要客户端重新发起请求
  • 扩展ViewModel传递草稿:通过ViewModel的属性把数据从控制器传递到各级局部视图,避开视图Model只读的限制
  • 保留ModelState:确保前端的asp-validation-summary和asp-validation-for能正常显示错误提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:22:35