.NET 8.0中Session存取值转指定类型返回null问题排查
解决方案
核心问题排查
你的问题出在三个关键点:
- 序列化与反序列化时Json配置不统一:序列化阶段没处理枚举转字符串,反序列化却用了,导致枚举格式不兼容
- 硬编码反序列化类型:
Deserialize方法固定转成UserData,但实际存储的是User类型(或其他类型),类型不匹配导致As转换失败 - 动态对象的类型信息丢失:.NET 8下Session只能存字节数组,存储时没记录原对象类型,读取时无法正确还原
具体修复步骤
1. 统一序列化/反序列化的Json配置
修改SerializeObject方法,加入枚举转字符串的转换器,确保序列化和反序列化规则一致:
private static byte[] SerializeObject(object obj) { if (obj == null) return null; var options = new JsonSerializerOptions { Converters = { new JsonStringEnumConverter() } }; string jsonString = JsonSerializer.Serialize(obj, options); return Encoding.UTF8.GetBytes(jsonString); }
2. 解决动态类型反序列化问题
因为SessionBag是动态对象,不同键对应不同类型,这里提供两种可行方案:
方案一:键名映射目标类型
通过键名判断要反序列化的类型,适合键名和类型一一对应的场景:
// 修改Deserialize方法,支持传入目标类型 private static object Deserialize(byte[] byteArray, Type targetType) { if (byteArray == null) return null; string jsonString = Encoding.UTF8.GetString(byteArray); var options = new JsonSerializerOptions { Converters = { new JsonStringEnumConverter() } }; return JsonSerializer.Deserialize(jsonString, targetType, options); } // 更新TryGetMember中的.NET 8代码块 #if NET8_0_OR_GREATER if (Session.TryGetValue(binder.Name, out byte[] val)) { // 根据键名匹配对应的类型,按需添加其他键的映射 Type targetType = binder.Name switch { "UserData" => typeof(UserData), "User" => typeof(User), _ => typeof(object) }; result = Deserialize(val, targetType); } else { result = null; } #endif
方案二:存储时附带类型信息
存储数据时同时保存原对象的类型信息,读取时根据类型信息反序列化,适合类型灵活多变的场景:
// 修改.NET 8下的存储逻辑,添加类型信息存储 #if NET8_0_OR_GREATER if (value != null) { Session.Set(key, SerializeObject(value)); // 存储类型的完全限定名 var typeBytes = Encoding.UTF8.GetBytes(value.GetType().AssemblyQualifiedName); Session.Set($"{key}_Type", typeBytes); } else { Session.Remove(key); Session.Remove($"{key}_Type"); } #endif // 更新TryGetMember中的.NET 8代码块 #if NET8_0_OR_GREATER if (Session.TryGetValue(binder.Name, out byte[] val) && Session.TryGetValue($"{binder.Name}_Type", out byte[] typeVal)) { var typeName = Encoding.UTF8.GetString(typeVal); var targetType = Type.GetType(typeName); result = targetType != null ? Deserialize(val, targetType) : null; } else { result = null; } #endif
3. 修正类型笔误
检查代码中UserData和User的对应关系:如果服务层实际存储的是User对象,要确保反序列化时的目标类型正确,避免因类型不匹配导致As转换返回null。
验证方法
- 在.NET 8环境下,将
User(或UserData)对象存入SessionBag.Current.UserData; - 执行
SessionBag.Current.UserData As UserData(对应实际类型),确认转换成功; - 检查枚举属性是否正确还原,无类型转换异常。
内容的提问来源于stack exchange,提问作者user3497702
相关产品推荐
相关产品推荐

