0

I slipped into a deep problem with sessions in app (asp.net core mvc). This kind of problem was never occurred to me till i was in Asp.net mvc.

Sessions are working fine and every value of session is retained when I check values of session using breakpoint in visual studio. But if I remove breakpoint and just run my app, then session values gets empty/null and this issue is intermittent. I can consider this as a big flaw/bug in .net core mvc.

I have checked few answers in Session variable value is getting null in ASP.NET Core and Session Lost in Asp.net Core application but none of them are working for me.

I have these settings in startup.cs

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseAuthentication();
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseSession();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                name: "areas",
                template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }


      services.Configure<CookiePolicyOptions>(options =>
                {
                    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                    options.CheckConsentNeeded = context => false;
                    options.MinimumSameSitePolicy = SameSiteMode.None;
                });
     services.AddSession(options =>
                {
                    options.IdleTimeout = TimeSpan.FromDays(1);
                });

  services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            }).AddCookie("Cookies", options =>
            {
                // Configure the client application to use sliding sessions
                options.SlidingExpiration = true;
                // Expire the session of 15 minutes of inactivity
                options.ExpireTimeSpan = TimeSpan.FromDays(1);
                if (appSettings.RedisCachingEnabled)
                {
                    options.EventsType = typeof(CustomCookieAuthenticationEvents);
                }
                options.Cookie.HttpOnly = true;
            })

I am now stuck to give build for this project because initially the sessions worked fine. Finally I am setting and getting session like this

UserController.cs class

public IActionResult SetUsers(int id) {
 _sessionData.users= some api call that get users;
  return RedirectToAction("LoadUsers", "Home", new
                {
                    area = "Admin",
                 });
}

Admin area/ homeController.cs

 public IActionResult LoadUsers() {
       var users = _sessionData.users;  // some users are lost when trying to get users from session
       // some time its completely null. But if applied breakpoint, it shows correct session                        
 }

This is my session class

public class SessionData : ISessionData
    {
        public IHttpContextAccessor _httpContextAccessor;


        public SessionData(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public List<User> users
        {
            get
            {
                var users= _httpContextAccessor.HttpContext.Session.GetObjectFromJson<List<User>>("users");
                if (users == null)
                {
                    users = new List<User>();
                }
                return users;
            }

            set
            {
                _httpContextAccessor.HttpContext.Session.SetObjectAsJson("users", value);
            }
        }

}
Sweetie
  • 1,298
  • 6
  • 24
  • 48

1 Answers1

0

You can create your own extension method for IHttpContextAccessor to save json data or retrieve it in a session. Here is an example

public static class Session
{
        private static IHttpContextAccessor _httpContextAccessor;
        private static ISession _session;

        public static void Initialized(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
            _session = _httpContextAccessor.HttpContext.Session;
        }
        public static bool SetObject(this IHttpContextAccessor httpContextAccessor, string key, object value)
        {
            bool status = false;
            try
            {
                Initialized(httpContextAccessor);
                _session.SetString(key, JsonConvert.SerializeObject(value));

                status = true;
            }
            catch (Exception ex)
            {

            }

            return status;

        }
        public static T GetObject<T>(this IHttpContextAccessor httpContextAccessor, string key)
        {
            try
            {
                Initialized(httpContextAccessor);
                var value = _session.GetString(key);
                return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
            }
            catch (Exception ex)
            {
                return default(T);
            }

        }
    
}

and in your controller, you inject an instance of IHttpContextAccessor in your constructor and you should be able to retrieve and save objects into a session

    public class SessionController : Controller
{
    private readonly UserInfo _user;

    public SessionController (IHttpContextAccessor iHttpContextAccessor)
    {
        _user = iHttpContextAccessor.GetObject<UserInfo>("user");//get session with 
                                  //key user 
    }


public IActionResult Login(LoginModel User)
    {
        
                        UserInfo userInfo = new UserInfo
                        {
                            Name = "name",
                            Id = 1
                        };
                        _iHttpContextAccessor.SetObject("user", userInfo);//set 
                                       //userinfo class into session
      }

User Info class:

 public class UserInfo
{

    public string Name{ get; set; }
    public int Id{ get; set; }
}
upsidedownwf
  • 134
  • 1
  • 3
  • 12