如何将Razor Page模型属性传递给_layout页面的asp-route-id标签助手
问题原因
- 你直接给
_layout.cshtml强绑定了VescovererWebApp.Pages.AccountModel类型,仅当访问Account页面时,Layout的Model类型匹配,所以悬停导航可以看到正确ID;跳转到其他页面对应的PageModel不是AccountModel类型,就会抛出类型不匹配的运行时异常。 - ViewData为空是因为它的生命周期仅限当前请求,页面跳转后触发新请求,新页面后台未给对应ViewData键赋值就会为空。
最优解决方案(适合传递登录用户ID的场景)
直接通过IHttpContextAccessor读取当前登录用户ID,无需跨页面传值:
- 先在项目启动配置(.NET 6+ 是
Program.cs,.NET Core 3.1 是Startup.cs)中注册服务:
// .NET 6+ 写法 builder.Services.AddHttpContextAccessor();
- 修改
_layout.cshtml顶部代码,删除原来的@model VescovererWebApp.Pages.AccountModel,替换为注入服务并取用户ID:
@inject IHttpContextAccessor HttpContextAccessor @using System.Security.Claims @{ // 读取当前登录用户的ID,和你之前AccountModel里的currentUserID值一致 var currentUserID = HttpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); }
- 把所有导航项的
asp-route-id="@Model.currentUserID"替换为asp-route-id="@currentUserID"即可,示例:
<a id="cu" class="nav-link text-dark" asp-area="" asp-page="/Account" asp-route-id="@currentUserID">Account</a>
备选方案(如果currentUserID不是登录用户ID,是自定义业务参数)
方案A:基类PageModel统一传值
- 定义公共基类页面模型:
public class BasePageModel : PageModel { // 统一存放需要传递给Layout的参数 public string currentUserID { get; set; } }
- 所有使用该Layout的页面的PageModel都继承
BasePageModel,在每个页面的OnGet/OnPost方法中给currentUserID赋值。 - 把_layout的Model声明改为
@model BasePageModel,即可兼容所有继承该基类的页面,不会出现类型不匹配错误。
方案B:Session存储
- 注册Session服务:
// Program.cs builder.Services.AddSession(opt => { opt.IdleTimeout = TimeSpan.FromMinutes(30); opt.Cookie.HttpOnly = true; opt.Cookie.IsEssential = true; }); // 中间件配置要加上,位置在UseAuthorization之前 app.UseSession();
- 在首次获取到
currentUserID的位置存入Session:
HttpContext.Session.SetString("currentUserID", 你的参数值);
- 在_layout中读取Session值使用即可:
@inject IHttpContextAccessor HttpContextAccessor @{ var currentUserID = HttpContextAccessor.HttpContext?.Session?.GetString("currentUserID"); }
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

