跳转页面后TempData变为null,如何在_Layout中持久化用户名?
这个问题的核心在于TempData的默认特性:它的数据仅在当前请求和下一次请求中有效,一旦被读取(除非手动保留)就会被标记为删除,后续请求自然拿不到数据。你用了TempData.Keep("username"),但这只能让它多存活一次请求,跳转到第三个页面时还是会被清理。下面给你几个可行的解决方案,按推荐程度排序:
1. 使用Claims(推荐的最佳实践)
这是ASP.NET身份验证体系的标准做法,把用户名存储到用户的身份声明中,完全不依赖TempData或Session,安全又可靠。
登录时的代码修改:
在处理登录逻辑的地方,创建ClaimsIdentity时添加用户名声明:
var username = model.Email.Split('@')[0]; var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), // 可添加其他必要声明,比如邮箱、角色等 }; var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
_Layout中的代码修改:
直接通过User对象获取用户名,无需再用TempData:
<li class="nav-item"> <h5 style="color:white"> Welcome, @User.Identity.Name</h5> </li>
如果需要更灵活的声明读取,也可以用@User.FindFirstValue(ClaimTypes.Name)来获取。
2. 使用Session存储
Session的数据会在整个用户会话周期内保持(直到会话过期或用户注销),比TempData的持久度高很多。
登录时的代码修改:
Session["username"] = model.Email.Split('@')[0];
_Layout中的代码修改:
<li class="nav-item"> <h5 style="color:white"> Welcome, @Session["username"]</h5> </li>
注意:要确保项目已启用Session,在Program.cs(或旧版的Startup.cs)中配置了Session中间件。
3. 用TempData.Peek()或重复调用Keep()
如果坚持要用TempData,可以用Peek()方法读取数据但不标记为删除,这样后续请求还能拿到:
_Layout中的代码修改:
@{ var username = TempData.Peek("username"); } <li class="nav-item"> <h5 style="color:white"> Welcome, @username</h5> </li>
或者,在每次读取TempData后手动调用Keep():
@{ var username = TempData["username"]; TempData.Keep("username"); } <li class="nav-item"> <h5 style="color:white"> Welcome, @username</h5> </li>
不过这种方法仅适合临时场景,长期来看还是Claims或Session的方案更靠谱。
总结一下,优先选择Claims方案,它和ASP.NET身份系统深度集成,安全性和可维护性都更好;简单场景下Session也能满足需求;TempData的Keep/Peek只能作为临时 workaround。
内容的提问来源于stack exchange,提问作者Hudas Iskaryote

