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

ASP.NET Core MVC页面跳转问题:无法从Overview返回PersonData页

ASP.NET Core MVC:从Overview页返回PersonData页并保留原有数据

问题背景

我有一个包含4个页面的ASP.NET Core MVC Web项目,页面流程如下:

  • 登录页:包含两个文本输入框和Next按钮;
  • PersonData页:展示登录用户的个人信息,同时包含邮箱地址和日期两个必填文本框,点击Next按钮后,所有数据将以只读形式展示在Overview页;
  • Overview页:点击Back按钮应返回PersonData页修改数据,但当前无法实现该功能。

核心问题:控制器的HttpPost PersonData方法中,ModelState.IsValid为true时会跳转至Overview页,但无法从Overview页返回PersonData页并保留原有数据。

问题原因

当前通过RedirectToAction("Overview", personDataModel)传递模型时,实际是将模型属性拼接为URL参数(GET请求),不仅存在数据暴露风险,且返回PersonData页时无法自动携带完整模型数据;同时Overview页的Back按钮未配置正确的数据传递逻辑。

解决方案

方案1:使用TempData存储模型(推荐轻量场景)

TempData适合跨请求临时存储数据,默认基于Session实现,读取后可手动保留数据。

修改控制器代码

public IActionResult Login()
{
    ViewData["Title"] = _localizer["Login"];
    return View();
}

// 支持接收传入模型,用于回显数据
public IActionResult PersonData(PersonDataModel personDataModel)
{
    ViewData["Title"] = _localizer["Persondata"].Value;
    // 若传入模型有有效数据,直接回显
    if (personDataModel != null && !string.IsNullOrWhiteSpace(personDataModel.PersonName))
    {
        return View(personDataModel);
    }
    // 加载默认个人信息
    var model = new PersonDataModel();
    model.PersonName = "Firstname Lastname";
    model.Street = "Street123";
    model.Zip = "12345";
    model.City = "Tokio";
            
    return View(model);
}

[HttpPost]
public ActionResult PersonData(PersonDataModel personDataModel)
{
    ViewData["Title"] = _localizer["Persondata"].Value;
            
    if (ModelState.IsValid)
    {
        // 将模型存入TempData,需确保PersonDataModel可序列化
        TempData["PersonData"] = personDataModel;
        return RedirectToAction("Overview");
    }

    return View(personDataModel);
}

public IActionResult Overview()
{
    ViewData["Title"] = _localizer["Overview"].Value;
    // 从TempData取出模型
    var personDataModel = TempData["PersonData"] as PersonDataModel;
    // 若TempData过期,跳转回PersonData页
    if (personDataModel == null)
    {
        return RedirectToAction("PersonData");
    }
    // 保留TempData,确保返回PersonData时可读取
    TempData.Keep("PersonData");
    return View(personDataModel);
}

修改Overview页的Back按钮

通过表单隐藏字段传递模型数据,确保返回PersonData时携带完整数据:

<form asp-action="PersonData" method="get">
    <!-- 生成模型所有属性的隐藏字段 -->
    @Html.HiddenFor(m => m.PersonName)
    @Html.HiddenFor(m => m.Street)
    @Html.HiddenFor(m => m.Zip)
    @Html.HiddenFor(m => m.City)
    @Html.HiddenFor(m => m.Email)
    @Html.HiddenFor(m => m.Date)
    <button type="submit" class="btn btn-primary">@HtmlLocalizer["Back"]</button>
</form>

<form asp-action="Confirmation" asp-controller="Statistics" method="post" class="needs-validation" novalidate>
    <button type="submit" class="btn btn-primary">@HtmlLocalizer["Confirmation"]</button> 
</form>

方案2:使用Session存储模型(适合多请求场景)

如果需要在多个页面间持久化数据,可使用Session替代TempData。

1. 启用Session

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

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30); // 设置超时时间
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// 在app.UseRouting()之后、app.UseAuthorization()之前添加
app.UseSession();

2. 添加Session扩展方法

创建扩展类用于序列化/反序列化模型:

public static class SessionExtensions
{
    public static void SetObjectAsJson(this ISession session, string key, object value)
    {
        session.SetString(key, JsonSerializer.Serialize(value));
    }

    public static T GetObjectFromJson<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default(T) : JsonSerializer.Deserialize<T>(value);
    }
}

3. 修改控制器代码

[HttpPost]
public ActionResult PersonData(PersonDataModel personDataModel)
{
    ViewData["Title"] = _localizer["Persondata"].Value;
            
    if (ModelState.IsValid)
    {
        // 将模型存入Session
        HttpContext.Session.SetObjectAsJson("PersonData", personDataModel);
        return RedirectToAction("Overview");
    }

    return View(personDataModel);
}

public IActionResult Overview()
{
    ViewData["Title"] = _localizer["Overview"].Value;
    var personDataModel = HttpContext.Session.GetObjectFromJson<PersonDataModel>("PersonData");
    if (personDataModel == null)
    {
        return RedirectToAction("PersonData");
    }
    return View(personDataModel);
}

public IActionResult PersonData(PersonDataModel personDataModel)
{
    ViewData["Title"] = _localizer["Persondata"].Value;
    // 优先使用传入模型,否则从Session读取
    if (personDataModel != null && !string.IsNullOrWhiteSpace(personDataModel.PersonName))
    {
        return View(personDataModel);
    }
    var savedModel = HttpContext.Session.GetObjectFromJson<PersonDataModel>("PersonData");
    if (savedModel != null)
    {
        return View(savedModel);
    }
    // 加载默认数据
    var model = new PersonDataModel();
    model.PersonName = "Firstname Lastname";
    model.Street = "Street123";
    model.Zip = "12345";
    model.City = "Tokio";
    return View(model);
}

4. Overview页的Back按钮同方案1

无需额外修改,使用隐藏字段传递数据即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 06:53:10