如何为Razor类库中的Razor页面统一添加路由前缀?
Blazor多模块RCL统一添加路由前缀方案
下面提供两种实用方案,无需手动修改每个页面的@page指令,就能给RCL内所有路由页面统一添加前缀:
方案一:.NET 7+ 项目文件配置(最简)
从.NET 7开始,Blazor原生支持给RCL设置全局路由基址,直接修改RCL的.csproj文件即可:
<PropertyGroup> <!-- 设置当前RCL的路由前缀,比如客户模块设为Customers --> <BlazorRouteBasePath>Customers</BlazorRouteBasePath> </PropertyGroup>
配置后,该RCL内所有页面的@page路由会自动拼接前缀:
- 原页面
@page "/Details/{id}" - 实际访问路径变为
localhost:5000/Customers/Details/1
每个模块的RCL单独配置对应的BlazorRouteBasePath即可实现路由隔离。
方案二:自定义路由约定(兼容低版本/灵活扩展)
如果使用.NET 6及以下版本,或者需要更灵活的路由修改逻辑,可以通过自定义IComponentModelConvention实现:
1. 创建路由约定类
在RCL项目中添加如下类,用于给路由添加前缀:
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Routing; using System.Reflection; public class ModuleRoutePrefixConvention : IComponentModelConvention { private readonly string _prefix; private readonly Assembly _moduleAssembly; public ModuleRoutePrefixConvention(string routePrefix, Assembly moduleAssembly) { _prefix = routePrefix.Trim('/'); _moduleAssembly = moduleAssembly; } public void Apply(ComponentModel model) { // 仅处理当前RCL内的路由组件(带@page指令的组件) if (model.Type.Assembly != _moduleAssembly) return; var routeAttributes = model.Type.GetCustomAttributes<RouteAttribute>(inherit: true); if (!routeAttributes.Any()) return; // 替换原有路由为带前缀的新路由 model.RouteValues.Clear(); foreach (var routeAttr in routeAttributes) { var originalRoute = routeAttr.Template.Trim('/'); var prefixedRoute = $"{_prefix}/{originalRoute}"; model.RouteValues.Add(prefixedRoute); } } }
2. 注册路由约定
在宿主项目(Blazor Server/WASM)的Program.cs中,注册该约定并指定前缀:
// 引用客户模块RCL的程序集 var customerModuleAssembly = typeof(CustomerModule.Pages.Details).Assembly; builder.Services.AddRazorComponents() .AddInteractiveServerComponents() // 根据项目类型选择Server/WASM .AddAdditionalAssemblies(customerModuleAssembly) .AddComponentModelConvention<ComponentBase>( new ModuleRoutePrefixConvention("Customers", customerModuleAssembly) );
也可以在RCL中封装扩展方法,简化宿主项目的调用:
// 客户模块RCL内的扩展方法 public static class CustomerModuleExtensions { public static RazorComponentsBuilder AddCustomerModule(this RazorComponentsBuilder builder) { var assembly = typeof(CustomerModuleExtensions).Assembly; builder.AddAdditionalAssemblies(assembly); builder.AddComponentModelConvention<ComponentBase>( new ModuleRoutePrefixConvention("Customers", assembly) ); return builder; } } // 宿主项目Program.cs调用 builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddCustomerModule();
注意事项
- 两种方案都不需要修改RCL内页面的
@page指令,原有路由模板保持不变即可。 - 若使用方案二,确保仅处理目标RCL的组件,避免影响宿主项目或其他模块的路由。
内容的提问来源于stack exchange,提问作者quintendc
相关产品推荐
相关产品推荐

