user3497702
user3497702

Reputation: 851

.NET 8.0 session storing and retrieving value then casting to specific type returns null

I have an ASP.NET MVC application on .NET 4.7.1 and it refers to a service layer project which target both .NET 4.7.1 and .NET 8.0.

The unit test project for the service project also targets both .NET 4.7.1 and .NET 8.0.

All unit tests pass with .NET 4.7.1.

The service project uses a SessionBag object that has conditional compiler for .NET 4.7.1 and .NET 8.0.

The Session in .NET 4.7.1 can store items without serializing and deserializing to specific type. So the unit tests work.

The Session in .NET 8.0 needs items as byte[] to store and on retrieval deserialize from byte[] to the specific class type needed.

This is the SessionBag class:

public class SessionBag : DynamicObject
{
    private static SessionBag current;
    private static object session;

    static SessionBag()
    {
        current = new SessionBag();
    }

    // Session Property 
    // Indexer
    // Other code
    
    // Setting data to Session 
    #if NET8_0_OR_GREATER
    if (value != null)
    {
        // Serialize object to byte[] and store in session
        Session.Set(key, SerializeObject(value));
    }
    else
    {
        Session.Remove(key);
    }
    #else
        Session.Add(key, value);
    #endif

    // Helper methods for serialization and deserialization using System.Text.Json
    private static byte[] SerializeObject(object obj)
    {
        if (obj == null) return null;
        string jsonString = JsonSerializer.Serialize(obj);
        return Encoding.UTF8.GetBytes(jsonString);
    }

    // Retrieving Data from Session
    // DynamicObject overrides to make SessionBag dynamic
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (Session != null)
        {
            #if NET8_0_OR_GREATER
                if (Session.TryGetValue(binder.Name, out byte[] val))
                {
                    result = Deserialize(val);  // Use Deserialize directly to determine the type
                }
                else
                {
                    result = null;
                }
            #else
                result = Session[binder.Name];
            #endif
        }
        else
        {
            result = null;
        }

        return true;
    }
            
    // Deserialize based on type checks (string, string[], UserInfo, UserRoles)
    private static object Deserialize(byte[] byteArray)
    {
        if (byteArray == null) 
            return null;

        string jsonString = Encoding.UTF8.GetString(byteArray);

        // Deserialize with custom options to handle enum as string
        var options = new JsonSerializerOptions
        {
            Converters = { new JsonStringEnumConverter() } // Enable string enum conversion
        };

        return JsonSerializer.Deserialize<UserData>(jsonString);  

        //return JsonSerializer.Deserialize<object>(jsonString);
    }       
}

The UserData class has many properties and one of them is an enum property.

The service layer code returns null on the conversion.

SessionBag.Current.UserData As UserData

This code works fine in .NET 4.7.1, but returns null on casting SessionBag.Current.UserData on .NET 8.0.

I found UserData class has one enum property, and is decorated as shown here, but it still fails.

Please advise.

public class User
{
    public decimal Id { get; set; }
    public string Name { get; set; }

    [JsonConverter(typeof(JsonStringEnumConverter))]
    public UserType Type { get; set; }
}

public enum UserType
{
    Type1 = 0,
    Type2 = 1,
    Type3 = 2,
}

Upvotes: 0

Views: 61

Answers (0)

Related Questions