简体   繁体   中英

.NET Core 3.1 Complex Session Wrapper Not Working

I am trying to create a complex session wrapper in .NET Core 3.1. I ran into an issue where my variables are not being set. This is the way I set up the session wrapper class.

public class SessionWrapper : ISessionWrapper
{
    private static IHttpContextAccessor context;
    public SessionWrapper(IHttpContextAccessor _context)
    {
        context = _context;
    }
    public static Course Course
    {
        get
        {

            var key = context.HttpContext.Session.GetString("course");
            if (key == null)
            {
                return default;
            }
            else
            {
                return JsonConvert.DeserializeObject<Course>(key);
            }
        }
        set
        {
            if(value != null)
            {
                context.HttpContext.Session.SetString("course", JsonConvert.SerializeObject(value));
            }
        }
    }
}

I configured my services to use session and the sessionwrapper.

 services.AddDistributedMemoryCache();
 services.AddSession();

 services.AddHttpContextAccessor();
 services.AddScoped<ISessionWrapper, SessionWrapper>();

I configured the pipeline to use session

app.UseSession(); 

In my controller, I am initializing course and set the session wrapper. Then, I am setting the course id to 4. It's not complaining, but the course id is not being set. It's always null. I've been looking at it for so and is getting frustrated. What am I missing here?

  Course myCourse = new Course();
  SessionWrapper.Course = myCourse;
  SessionWrapper.Course.Id = "4"

I feel like your wrapper in itself isn't really the best approach to do this. A self-aware subclass of Course that has the 'know how' to store itself in Session, seems more logical to me. That way you are freeing your controller(s) from the responsibility for managing the persistence.

public abstract class Course
{
   public abstract int Id { get; set; }
}

public class SessionCourse : Course
{
    private int _id;
    public override int Id 
    { 
        get => _id; 
        set { _id = value; UpdateSession(); }
    }

    // The GetCourse method is a factory for creating the SessionCourse objects 
    // and providing it with a ISession object so they can store themselves.

    public static Course GetCourse(IServiceProvider services)
    {
        ISession session = services.GetRequiredService<IHttpContextAccessor>()?.HttpContext.Session;
        SessionCourse course = session?.GetJson<SessionCourse>("Course") ?? new SessionCourse();
        course.Session = session;
        return course;
    }

    [JsonIgnore]
    private ISession Session { get; set; }

    private void UpdateSession() {
        Session.SetJson("Course", this);
    }
}

Now the trick is to satisfy requests for the Course object with the SessionCourse object that will store itself in session. You can do that by adding a scoped service with a lambda expression for the course object. The result is that requests for the Course service will return the SessionCourse object.

services.AddScoped<Course>(sp => SessionCourse.GetCourse(sp));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

So the benefit of creating this kind of service is that it allows you to simplify the controllers where Course objects are used.

public class CourseController : Controller 
{
    private Course course;

    public CartController(Course courseService) 
    {
        course = courseService;
    }

    public void SetCourseId()
    {
        course.Id = "4";
    }

SessionExtension.cs defines extension methods for adding objects to the session.

public static class SessionExtensions {

    public static void SetJson(this ISession session, string key, object value) {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T GetJson<T>(this ISession session, string key) {
        var sessionData = session.GetString(key);
        return sessionData == null ? default(T) : JsonConvert.DeserializeObject<T>(sessionData);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM