HttpContext.Session not maintaining state

C Ruckman picture C Ruckman · Oct 2, 2018 · Viewed 12.2k times · Source

I have been all over the net to find out what is wrong with my use of HttpContext.Session. It appears that the session is being set when I set it, but after it leaves the function, I cannot access it. I have examined my Startup.cs file to make sure everything is added correctly and have installed the proper NuGet packages.

In my controller class where I actually use the sessions, I have the following code:

    /// <summary>
    /// Check to see if user exists.  If yes, go to the administrator interface,
    /// else return to the login page.
    /// </summary>
    /// <param name="administrator"></param>
    /// <returns></returns>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult AdminLogin([Bind("UserName", "Password")] Administrator administrator)
    {
        try
        {
            var admin = _context.Administrators.Where(x => x.UserName == administrator.UserName
                && x.Password == administrator.Password).FirstOrDefault();

            if (admin != null)
            {
                HttpContext.Session.SetString("IsAdmin", "true");
                _httpContextAccessor.HttpContext.Response.Cookies.Append("IsAdmin", "true");
            }

            return RedirectToAction("Index");
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    /// <summary>
    /// Shows the administrator interface
    /// </summary>
    public IActionResult Index()
    {
        if (HttpContext.Session.GetString("IsAdmin") == "true"
            || _httpContextAccessor.HttpContext.Request.Cookies["IsAdmin"] == "true")
        {
            ViewData["isAdmin"] = "true";
            HttpContext.Session.SetString("IsAdmin", "true");
            ViewData["Title"] = "Administrator Page";
            ViewData["Message"] = "Administrator Page";
            return View();
        }
        else
        {
            return RedirectToAction("AdminLogin");
        }
    }

As you can see, I am setting a session variable (IsAdmin) in the AdminLogin function and then trying to access that session in the Index view. I have ValidateAntiForgeryToken, which I thought might have been my problem, but even if I remove it, my sessions are not persisted. I'm also trying to use cookies as a work-around, but those aren't persisting either. I can post more code if anyone is willing to help me out. If I can't get this to work, I will have to start over and not use Asp.NET Core. The rest of my application will eventually have to use sessions as well.

Here is my startup.cs, just to make sure that it is, indeed, set up correctly...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using OM2018a.Data;
using Microsoft.EntityFrameworkCore;

namespace OM2018a
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddDbContext<OM2018Context>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            // Add MVC services to the services container.
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddDistributedMemoryCache(); // Adds a default in-memory implementation of IDistributedCache
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(15);
            });

            services.AddHttpContextAccessor();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseCookiePolicy();

            // IMPORTANT: This session call MUST go before UseMvc()
            app.UseSession();

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

Answer

C Ruckman picture C Ruckman · Oct 3, 2018

I found the answer! Session variable value is always getting null in ASP.NET Core 2.1

I had to change options.CheckConsentNeeded = context => true; to false and it worked!