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
相关产品推荐
相关产品推荐

