Blazor开发中如何将泛型对象传递至其他页面?
解决方案
Blazor 路由本身确实不支持直接传递复杂类型对象,针对你的泛型网格组件跳转场景,有两种成熟的实现方案:
方案1:依赖注入状态服务(推荐,性能最优,无序列化开销)
适合不需要支持页面刷新、链接分享的内部业务场景,Server 和 WASM 模式都兼容
第一步:创建配套服务
// 泛型状态容器,存储对应类型的待传递对象 public class EntityCreationState<TEntity> { public TEntity? PendingEntity { get; set; } public void Clear() => PendingEntity = default; } // 实体类型和创建页路由映射服务 public class EntityRouteMappingService { private readonly Dictionary<Type, string> _routeMaps = new() { { typeof(Employee), "/create/employee" }, { typeof(Customer), "/create/customer" } // 新增实体类型只需在这里补映射关系即可 }; public string GetCreationRoute(Type entityType) { if (_routeMaps.TryGetValue(entityType, out var route)) return route; throw new NotSupportedException($"未配置{entityType.Name}对应的创建页路由"); } }
第二步:注册服务
在 Program.cs 中添加注册逻辑:
// Blazor Server 用 Scoped,WASM 用 Singleton 即可 builder.Services.AddScoped(typeof(EntityCreationState<>)); builder.Services.AddScoped<EntityRouteMappingService>();
第三步:修改 GenericGrid.razor 按钮逻辑
@typeparam TItem @inject NavigationManager NavManager @inject EntityCreationState<TItem> CreationState @inject EntityRouteMappingService RouteMapping ...grid layout... <GridToolBar> <GridCommandButton Icon="add" OnClick="GoToCreatePage">New @typeof(TItem).Name</GridCommandButton> </GridToolBar> ...rest of grid layout... @code { [Parameter] public TItem Entity { get; set; } private void GoToCreatePage() { // 存储待传递的泛型对象 CreationState.PendingEntity = Entity; // 跳转到对应类型的创建页 var createRoute = RouteMapping.GetCreationRoute(typeof(TItem)); NavManager.NavigateTo(createRoute); } }
第四步:创建页读取状态
以员工创建页为例:
@page "/create/employee" @inject EntityCreationState<Employee> CreationState @implements IDisposable <!-- 你的创建表单代码 --> @code { private Employee _currentEntity; protected override void OnInitialized() { // 读取传递过来的对象,为空则初始化新对象 _currentEntity = CreationState.PendingEntity ?? new Employee(); // 读取后立即清空状态,避免下次进入页面复用旧数据 CreationState.Clear(); } public void Dispose() => CreationState.Clear(); }
方案2:序列化传参(适合需要支持页面刷新、链接分享的场景)
如果要求用户刷新页面、或者分享链接后仍然能保留传递的对象参数,可以用序列化转Base64的方式放到查询参数中传递
第一步:修改 GenericGrid 跳转逻辑
private void GoToCreatePage() { if (Entity == null) return; // 序列化对象为JSON后转Base64,避免特殊字符破坏路由结构 var json = System.Text.Json.JsonSerializer.Serialize(Entity); var base64Str = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(json)); var createRoute = RouteMapping.GetCreationRoute(typeof(TItem)); NavManager.NavigateTo($"{createRoute}?data={base64Str}"); }
第二步:创建页读取参数反序列化
@page "/create/employee" @inject NavigationManager NavManager @implements IDisposable <!-- 你的创建表单代码 --> @code { private Employee _currentEntity; private NavigationManager _navManager; protected override void OnInitialized() { _navManager = NavManager; _navManager.LocationChanged += OnLocationChanged; ParseQueryParams(); } private void ParseQueryParams() { var uri = new Uri(_navManager.Uri); var queryParams = System.Web.HttpUtility.ParseQueryString(uri.Query); var data = queryParams["data"]; if (!string.IsNullOrEmpty(data)) { try { var bytes = Convert.FromBase64String(data); var json = System.Text.Encoding.UTF8.GetString(bytes); _currentEntity = System.Text.Json.JsonSerializer.Deserialize<Employee>(json) ?? new Employee(); return; } catch { /* 非法参数直接走默认创建逻辑 */ } } _currentEntity = new Employee(); } private void OnLocationChanged(object sender, LocationChangedEventArgs e) { ParseQueryParams(); } public void Dispose() { _navManager.LocationChanged -= OnLocationChanged; } }
内容的提问来源于stack exchange,提问作者Stefan Jaspers
相关产品推荐
相关产品推荐

