You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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。


验证方法

  1. 在.NET 8环境下,将User(或UserData)对象存入SessionBag.Current.UserData;
  2. 执行SessionBag.Current.UserData As UserData(对应实际类型),确认转换成功;
  3. 检查枚举属性是否正确还原,无类型转换异常。

内容的提问来源于stack exchange,提问作者user3497702

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:44:52