跨页面传递值作为路由参数的优选方案,实现下拉选择状态全局同步
实现方案
1. 统一配置全局路由模板
先给所有页面路由追加可选的branch参数,确保跳转任何页面都能携带该参数:
// Program.cs 中Razor Pages配置示例 builder.Services.AddRazorPages() .AddRazorPagesOptions(options => { // 给根目录下所有页面的路由末尾添加可选branch参数 options.Conventions.AddFolderRouteModelConvention("/", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template += "/{branch?}"; } }); }); // 别忘了注册IHttpContextAccessor builder.Services.AddHttpContextAccessor();
2. 封装BranchSelector视图组件
把下拉的查询、选中项绑定、跳转逻辑全部封装到视图组件,无需每个页面传递参数:
视图组件逻辑代码
// BranchSelectorViewComponent.cs public class BranchSelectorViewComponent : ViewComponent { private readonly YourDbContext _context; private readonly IHttpContextAccessor _httpContextAccessor; public BranchSelectorViewComponent(YourDbContext context, IHttpContextAccessor httpContextAccessor) { _context = context; _httpContextAccessor = httpContextAccessor; } public async Task<IViewComponentResult> InvokeAsync() { // 优先级:当前路由参数 > Cookie存储值 var currentBranch = RouteData.Values["branch"]?.ToString() ?? _httpContextAccessor.HttpContext.Request.Cookies["SelectedBranch"]; // 替换为你获取当前用户ColleagueID的逻辑 var userColleague = int.Parse(User.FindFirstValue("ColleagueID")); var options = await _context.BranchAssignment .Where(a => a.ColleagueID == userColleague) .IgnoreQueryFilters() .OrderBy(a => a.Branch.BranchNumber) .Select(a => new SelectListItem { Value = a.BranchID.ToString(), Text = a.Branch.BranchName, Selected = a.BranchID.ToString() == currentBranch }) .ToListAsync(); return View(options); } }
视图组件页面代码
在Views/Shared/Components/BranchSelector/Default.cshtml中添加渲染和交互逻辑:
@model List<SelectListItem> <select id="branchSelect" class="form-select" asp-items="Model" onchange="handleBranchChange(this.value)"> </select> <script> function handleBranchChange(selectedBranch) { const pathSegments = window.location.pathname.split('/').filter(seg => seg); let newPathSegments; // 替换已有branch参数,没有则追加 if (pathSegments.length > 0 && !isNaN(pathSegments.at(-1))) { newPathSegments = [...pathSegments.slice(0, -1), selectedBranch]; } else { newPathSegments = [...pathSegments, selectedBranch]; } const newPath = '/' + newPathSegments.join('/'); // 存储选中值到Cookie,有效期7天 document.cookie = `SelectedBranch=${selectedBranch};path=/;max-age=${7 * 24 * 60 * 60};SameSite=Lax`; // 跳转到新地址 window.location.href = newPath; } </script>
3. 全局挂载下拉组件
直接在_Layout.cshtml的导航栏位置引入视图组件,全局仅需引入一次:
<!-- 导航栏对应位置添加 --> @await Component.InvokeAsync("BranchSelector")
4. 页面获取选中参数
各页面的OnGet方法直接从路由参数读取branch值即可:
public IActionResult OnGet(string branch) { // 无路由参数时读取Cookie重定向补全路由 if (string.IsNullOrEmpty(branch)) { var savedBranch = Request.Cookies["SelectedBranch"]; if (!string.IsNullOrEmpty(savedBranch)) { return Redirect($"/{RouteData.Values["Page"]}/{savedBranch}"); } // 无存储值时可跳转到默认branch或者提示选择 } // 业务逻辑直接使用branch参数 return Page(); }
方案优势
- 逻辑完全复用:下拉的查询、渲染、交互全部封装在视图组件中,无需每个页面重复编写
- 路由参数友好:选中值直接体现在URL中,用户分享链接时可直接携带选中的branch参数
- 记忆逻辑可靠:同时通过路由和Cookie两层存储选中值,跳转不同页面自动继承选中状态
- 符合业内常规实现:全局公共组件+路由参数+Cookie兜底的方案是后台系统多分支/多租户切换的常用实现方式
内容的提问来源于stack exchange,提问作者Colin-G-Davidson
相关产品推荐
相关产品推荐

