Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET core 2.1 session

In ASP.NET core 2.1, I cannot access session variables.

While debugging I have noticed that in every request the session ID changes (HttpContex.Session.Id)

Did I make mistake in session configuration?

Startup.cs

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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        // Adds a default in-memory implementation of IDistributedCache.
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(1000);
            options.Cookie.HttpOnly = true;
        });
    }

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

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

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

Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

While debugging i have noticed that in every request session id changes (HttpContex.Session.Id)

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ucms6.Models;

namespace ucms6.Controllers
{
public class HomeController : Controller
{
    const string SessionKeyName = "_Name";
    const string SessionKeyYearsMember = "_YearsMember";
    const string SessionKeyDate = "_Date";
    public IActionResult Index()
    {
        // Requires using Microsoft.AspNetCore.Http;
        HttpContext.Session.SetString(SessionKeyName, "Rick");
        HttpContext.Session.SetInt32(SessionKeyYearsMember, 3);
        return RedirectToAction("SessionNameYears");
      //  return View();
    }
    public IActionResult SessionNameYears()
    {
        var name = HttpContext.Session.GetString(SessionKeyName);
        var yearsMember = HttpContext.Session.GetInt32(SessionKeyYearsMember);

        return Content($"Name: \"{name}\",  Membership years: \"{yearsMember}\"");
    }
    public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        return View();
    }
like image 516
ugur Avatar asked Mar 16 '18 09:03

ugur


People also ask

Can we use session in ASP.NET Core?

Session state is an ASP.NET Core scenario for storage of user data while the user browses a web app. Session state uses a store maintained by the app to persist data across requests from a client. The session data is backed by a cache and considered ephemeral data.

How check session expired in ASP.NET Core?

You can check the HttpContext. Current. User. Identity.

What is IHttpContextAccessor?

It stores the request and response information, such as the properties of request, request-related services, and any data to/from the request or errors, if there are any. ASP.NET Core applications access the HTTPContext through the IHttpContextAccessor interface. The HttpContextAccessor class implements it.


3 Answers

In the ConfigureServices() method of the Startup class, Set options.CheckConsentNeeded = context => false; as follows:

services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => false; // Default is true, make it false
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });
like image 137
TanvirArjel Avatar answered Oct 08 '22 20:10

TanvirArjel


The solution is to mark the session cookie as essential.

public void ConfigureServices(IServiceCollection services)
{
    //...
    services.AddSession(opt =>
    {
        opt.Cookie.IsEssential = true;
    });
    //...
}

The documentation about the flag states:

Indicates if this cookie is essential for the application to function correctly. If true then consent policy checks may be bypassed. The default value is false.

This will keep the cookie policy options intact and the session is still working as expected because CookiePolicyOptions.CheckConsentNeeded only affects non-essential cookies.

like image 26
SeriousM Avatar answered Oct 08 '22 18:10

SeriousM


The default distributed cache store in ASP.NET Core is in-memory. Since sessions use distributed cache, that means your session store is also in-memory. Things stored in memory are process-bound, so if the process terminates, everything stored in memory goes along with it. Finally, when you stop debugging, the application process is terminated. That then means every time you start and stop debugging, you have an entirely new session store.

There's a couple of routes you can take. First, if you just want to run the site, without debugging it, you can use CTRL+F5. This will kick off IIS Express and load your web app, without starting all the debugging machinery along with it. You can then proceed to make as many requests as you like, and it will all hit the same process (meaning your session store will be intact). This is great for doing the frontend side of development, as you can modify your Razor views, CSS, JS, etc. and see those changes without have to stop and start debugging again. However, if you make any C# code changes (class, controller, etc.), Visual Studio will kick off a build, which will terminate the application and then restart it. Your site keeps running as if nothing happened, but anything stored in-memory, including your sessions will be gone. It's at least better than debugging constantly, though.

Second, you can simply use a persistent store in development, as well (you should already be setup to use a persistent store in production, so fix that ASAP, if not). You can use something like SQL Server or Redis in development, just like you would in production. The SQL store can be added to your existing development database, so you don't actually need to install SQL Server. You can also install a local copy of Redis and just run it off of localhost, if you prefer that route. With either approach, your distributed cache, and your sessions along with it, will be stored in something external to the application, so starting and stopping your application will have no effect on what's stored there.

like image 39
Chris Pratt Avatar answered Oct 08 '22 20:10

Chris Pratt