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

ASP.NET Core Razor视图跨页面保留数据完成Mentee注册提交

ASP.NET Core 跨页面保存注册数据方案(导师匹配软件)

针对你提到的两步式学员注册场景,以下是几种可靠的实现方案,均能解决跨页面数据丢失问题,最终将两页数据合并提交至数据库:

方案1:使用TempData存储临时数据

TempData专为跨请求临时数据传递设计,默认基于Session实现,数据在首次读取后自动失效,适合这种短流程的页面跳转场景。

步骤1:配置Session(若未开启)

在Program.cs中添加Session服务配置:

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30); // 设置30分钟超时,适配用户操作时长
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// 在路由之后启用Session
app.UseSession();

步骤2:定义统一的注册ViewModel

public class MenteeRegistrationViewModel
{
    [Required]
    public string Name { get; set; }
    
    [Required]
    [EmailAddress]
    public string Email { get; set; }
    
    [Required]
    public string Occupation { get; set; } // 若用枚举可改为枚举类型
    
    public int SelectedMentorId { get; set; }
}

// 导师展示ViewModel
public class MentorViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Occupation { get; set; }
    public string Bio { get; set; }
}

步骤3:Controller逻辑实现

public class MenteeController : Controller
{
    private readonly IMentorService _mentorService;
    private readonly AppDbContext _context;

    public MenteeController(IMentorService mentorService, AppDbContext context)
    {
        _mentorService = mentorService;
        _context = context;
    }

    // 第一页注册视图
    public IActionResult Step1()
    {
        return View();
    }

    // 处理第一页提交,跳转至导师选择页
    [HttpPost]
    public IActionResult Step1(MenteeRegistrationViewModel model)
    {
        if (!ModelState.IsValid) return View(model);
        
        // 序列化第一页数据存入TempData
        TempData["MenteeStep1Data"] = JsonSerializer.Serialize(model);
        
        // 根据职业筛选对应导师
        var mentors = _mentorService.GetMentorsByOccupation(model.Occupation);
        return View("Step2", mentors);
    }

    // 导师选择页视图
    public IActionResult Step2(List<MentorViewModel> mentors)
    {
        return View(mentors);
    }

    // 处理最终注册提交
    [HttpPost]
    public IActionResult Complete(int selectedMentorId)
    {
        // 读取并反序列化TempData中的第一页数据
        if (!TempData.TryGetValue("MenteeStep1Data", out var step1DataObj))
        {
            return RedirectToAction("Step1"); // 数据丢失则返回第一页
        }

        var step1Data = JsonSerializer.Deserialize<MenteeRegistrationViewModel>(step1DataObj.ToString());
        
        // 组装实体并保存到数据库
        var mentee = new Mentee
        {
            Name = step1Data.Name,
            Email = step1Data.Email,
            Occupation = step1Data.Occupation,
            MentorId = selectedMentorId
        };

        _context.Mentees.Add(mentee);
        _context.SaveChanges();
        
        return RedirectToAction("RegistrationSuccess");
    }
}

步骤4:Step2视图(导师卡片列表)

@model List<MentorViewModel>

<form asp-action="Complete" method="post">
    @foreach (var mentor in Model)
    {
        <div class="mentor-card p-4 border rounded mb-3">
            <h3>@mentor.Name</h3>
            <p class="text-muted">@mentor.Occupation</p>
            <p>@mentor.Bio</p>
            <div class="mt-2">
                <input type="radio" name="selectedMentorId" value="@mentor.Id" required>
                <label class="ms-1">选择这位导师</label>
            </div>
        </div>
    }
    <button type="submit" class="btn btn-primary">完成注册</button>
</form>

方案2:使用隐藏字段传递第一页数据

无需依赖Session/TempData,将第一页数据作为隐藏字段嵌入第二页表单,提交时一同发送至服务器,适合对Session配置有顾虑的场景。

Controller逻辑调整

[HttpPost]
public IActionResult Step1(MenteeRegistrationViewModel model)
{
    if (!ModelState.IsValid) return View(model);
    
    var mentors = _mentorService.GetMentorsByOccupation(model.Occupation);
    ViewBag.Step1Data = model; // 将第一页数据传递到视图
    return View("Step2", mentors);
}

[HttpPost]
public IActionResult Complete(MenteeRegistrationViewModel model)
{
    if (!ModelState.IsValid)
    {
        // 验证失败时重新加载导师列表
        var mentors = _mentorService.GetMentorsByOccupation(model.Occupation);
        ViewBag.Step1Data = model;
        return View("Step2", mentors);
    }

    var mentee = new Mentee
    {
        Name = model.Name,
        Email = model.Email,
        Occupation = model.Occupation,
        MentorId = model.SelectedMentorId
    };

    _context.Mentees.Add(mentee);
    _context.SaveChanges();
    
    return RedirectToAction("RegistrationSuccess");
}

Step2视图调整

@model List<MentorViewModel>
@{
    var step1Data = ViewBag.Step1Data as MenteeRegistrationViewModel;
}

<form asp-action="Complete" method="post">
    <!-- 隐藏字段存储第一页数据 -->
    <input type="hidden" asp-for="@step1Data.Name" />
    <input type="hidden" asp-for="@step1Data.Email" />
    <input type="hidden" asp-for="@step1Data.Occupation" />

    @foreach (var mentor in Model)
    {
        <div class="mentor-card p-4 border rounded mb-3">
            <h3>@mentor.Name</h3>
            <p class="text-muted">@mentor.Occupation</p>
            <p>@mentor.Bio</p>
            <div class="mt-2">
                <input type="radio" asp-for="@step1Data.SelectedMentorId" value="@mentor.Id" required>
                <label class="ms-1">选择这位导师</label>
            </div>
        </div>
    }
    <button type="submit" class="btn btn-primary">完成注册</button>
</form>

方案3:使用Session存储数据

与TempData类似,但Session数据会保留至超时或手动清除,适合需要更长时间保留数据的场景,实现逻辑与TempData基本一致,仅需将TempData替换为HttpContext.Session:

Controller核心代码

[HttpPost]
public IActionResult Step1(MenteeRegistrationViewModel model)
{
    if (!ModelState.IsValid) return View(model);
    
    HttpContext.Session.SetString("MenteeStep1Data", JsonSerializer.Serialize(model));
    var mentors = _mentorService.GetMentorsByOccupation(model.Occupation);
    return View("Step2", mentors);
}

[HttpPost]
public IActionResult Complete(int selectedMentorId)
{
    var step1DataJson = HttpContext.Session.GetString("MenteeStep1Data");
    if (string.IsNullOrEmpty(step1DataJson)) return RedirectToAction("Step1");
    
    var step1Data = JsonSerializer.Deserialize<MenteeRegistrationViewModel>(step1DataJson);
    // 后续保存逻辑同方案1
    
    // 注册完成后清除Session数据
    HttpContext.Session.Remove("MenteeStep1Data");
    return RedirectToAction("RegistrationSuccess");
}

注意事项

  • 数据验证:服务器端必须对所有提交的数据重新验证,避免前端篡改隐藏字段或传递无效数据
  • 敏感数据保护:若使用隐藏字段传递邮箱等敏感信息,需确保服务器端验证逻辑严谨;若使用QueryString传递(不推荐),需对数据加密
  • 超时处理:Session/TempData需设置合理的超时时间,避免用户操作过慢导致数据丢失

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:22:00