Blazor Server(.NET Core 6)中ProtectedSessionStorage使用异常:代码执行退出与序列化错误排查问询
让我们一步步解决你遇到的两个问题:
1. 初始代码中「直接退出作用域」的问题
你最初的OnInitialized方法用了async void,这是Blazor组件生命周期方法的大忌!
Blazor的组件生命周期方法(比如OnInitialized)如果需要异步操作,必须返回async Task而不是async void。async void主要用于UI事件处理,在生命周期方法中使用它会导致Blazor框架无法追踪异步任务的完成状态,看起来就像是代码「直接退出了作用域」,后续代码不会执行,而且异常也很难被捕获。
修正后的代码应该是这样:
@code { [Inject] public SessionService SessionService { get; set; } = default!; // 把async void改成async Task,推荐用OnInitializedAsync更符合异步规范 protected override async Task OnInitializedAsync() { await InitUser(); // 必须await异步方法,确保执行完成 LoadInterface(); } protected async Task InitUser() { try { User user = new User("id", "location"); await SessionService.SetUserProperty(user); // 现在这部分代码会正常执行了 if(/* 你的检查条件 */) { // 一些其他检查 } } catch(Exception ex) { // 现在异常也能被正确捕获 Console.WriteLine($"初始化用户出错:{ex.Message}"); } } }
2. 浏览器控制台的序列化/反序列化错误
这个错误的核心是你的User类构造函数参数和类属性不匹配,导致System.Text.Json无法完成反序列化。
错误信息明确指出:
Each parameter in the deserialization constructor on type 'MyProject.Models.Shared.User' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object.
举个例子,假设你的User类是这样写的:
public class User { // 属性名是UserId和UserLocation public string UserId { get; set; } public string UserLocation { get; set; } // 构造函数参数是id和location,和属性名不匹配 public User(string id, string location) { UserId = id; UserLocation = location; } }
这时Json序列化器无法把构造函数的id参数映射到UserId属性,就会抛出错误。你可以通过以下几种方式解决:
方法一:让构造函数参数名和属性名匹配(大小写不敏感)
修改构造函数参数名,和属性名保持一致:
public class User { public string UserId { get; set; } public string UserLocation { get; set; } // 参数名改成userId和userLocation,和属性名对应 public User(string userId, string userLocation) { UserId = userId; UserLocation = userLocation; } }
方法二:给属性添加JsonPropertyName特性
如果不想修改构造函数参数名,可以用特性明确指定参数和属性的映射关系:
using System.Text.Json.Serialization; public class User { [JsonPropertyName("id")] // 指定序列化时对应"id"字段 public string UserId { get; set; } [JsonPropertyName("location")] // 指定序列化时对应"location"字段 public string UserLocation { get; set; } public User(string id, string location) { UserId = id; UserLocation = location; } }
方法三:添加无参构造函数
如果你的User类不需要依赖构造函数初始化,添加一个无参构造函数也能解决问题(Json序列化器可以通过无参构造函数创建实例,再反射赋值属性):
public class User { public string UserId { get; set; } public string UserLocation { get; set; } // 添加无参构造函数 public User() { } public User(string id, string location) { UserId = id; UserLocation = location; } }
总结
- 组件生命周期异步方法必须返回
Task,用async Task代替async void; - 确保
User类的构造函数参数和属性能被Json序列化器正确映射,选择上面任意一种方法都可以解决序列化错误。
内容的提问来源于stack exchange,提问作者Berzohr

