Blazor中如何全局条件重定向用户?支持例外页面配置
实现全局Foo选择检查(类似内置授权机制)
你可以通过路由导航拦截+自定义属性的方式实现这个需求,和[Authorize]的工作逻辑一致:全局默认强制检查Foo选择,例外页面通过属性跳过。以下是具体实现步骤:
1. 定义自定义标记属性
创建一个用于标记页面是否需要Foo选择的属性,默认启用检查:
using System; [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] public class RequiresFooSelectionAttribute : Attribute { public bool IsRequired { get; set; } = true; public RequiresFooSelectionAttribute(bool isRequired = true) { IsRequired = isRequired; } }
2. 注册全局状态服务
确保你的CascadingAppState是可注入的Scoped服务(用于共享Foo选择状态和返回地址):
public class CascadingAppState { // 标记Foo是否已选择 public bool FooSelected { get; set; } // 保存用户原本要访问的地址,方便选择后跳转 public string ReturnUrl { get; set; } }
在Program.cs中注册:
builder.Services.AddScoped<CascadingAppState>();
3. 全局导航拦截逻辑
修改App.razor中的Router组件,通过OnNavigateAsync回调拦截所有路由导航,检查目标页面的属性和Foo状态:
@inject NavigationManager NavManager @inject CascadingAppState AppState <Router AppAssembly="@typeof(App).Assembly" OnNavigateAsync="@OnNavigateAsync"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <LayoutView Layout="@typeof(MainLayout)"> <p role="alert">Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router> @code { private async Task OnNavigateAsync(NavigationContext context) { // 获取当前要跳转的页面类型 var pageType = context.RouteData.PageType; // 读取页面的自定义属性:没有标记则默认需要检查 var fooAttribute = pageType.GetCustomAttribute<RequiresFooSelectionAttribute>(); bool requiresFoo = fooAttribute?.IsRequired ?? true; // 如果需要检查且未选择Foo,则重定向到选择页面 if (requiresFoo && !AppState.FooSelected) { // 保存原地址 AppState.ReturnUrl = context.Location; // 跳转至Foo选择页 NavManager.NavigateTo("/select-foo", forceLoad: false); // 阻止当前导航 context.PreventNavigation(); } } }
4. 配置例外页面
对于不需要检查的页面(比如Foo选择页本身、登录页等),只需添加@attribute [RequiresFooSelection(false)]即可跳过检查:
@page "/select-foo" @attribute [RequiresFooSelection(false)] <h3>请选择Foo</h3> <button @onclick="ConfirmSelection">确认选择</button> @code { [Inject] private CascadingAppState AppState { get; set; } [Inject] private NavigationManager NavManager { get; set; } private void ConfirmSelection() { // 标记Foo已选择 AppState.FooSelected = true; // 跳转回用户原本要访问的页面(默认首页) var returnUrl = AppState.ReturnUrl ?? "/"; NavManager.NavigateTo(returnUrl); } }
为什么之前的尝试没生效?
Blazor不会自动处理自定义属性的逻辑,[Authorize]是框架内置了导航拦截和检查逻辑的。你需要手动通过Router的导航回调,读取页面属性并执行对应的检查逻辑,才能实现类似的全局控制效果。
内容的提问来源于stack exchange,提问作者mmcfly
相关产品推荐
相关产品推荐

