Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store and restore cookies with ASP.NET Core 2.0?

I created a sample web application with ASP.NET Core to test the storage and retrieval of the cookie. Unfortunately, I'm not able to store cookies.

I've read these questions for my problem:

Cookies in ASP.NET Core rc2

Create cookie with ASP.NET Core

Cookies and ASP.NET Core

But unfortunately I did not find a good answer.

I will first request an IndexA action to store the cookie. The code runs without any errors,but when I request IndexB action. Does not find the specified value

This is IndexA Action:

public IActionResult IndexA()
{
   Response.Cookies.Append("mykey", "myvalue",
    new CookieOptions()
    {
        Expires = DateTime.Now.AddMinutes(10)
    });
  return View();
}

This is IndexB Action:

public IActionResult IndexB()
{
   var cookie = Request.Cookies["mykey"];
   return View();
}

And This is Startup Class:

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);
    }

    // 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();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}
like image 981
Ahmad Javadi Nejad Avatar asked Aug 20 '18 13:08

Ahmad Javadi Nejad


Video Answer


3 Answers

I think it might have to do with the GDPR-related feature that ASP.NET Core 2.1 ships with. My understanding is that it allows websites to define which cookies are essential or not for the browser, and the non-essential ones won't be sent.

The first thing I can think of is to simply remove the check for consent for non-essential cookies. Do not do this in production as you might violate regulation!. Change:

services.Configure<CookiePolicyOptions>(options =>
{
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});

to

services.Configure<CookiePolicyOptions>(options =>
{
    // No consent check needed here
    options.CheckConsentNeeded = context => false;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});

The second potential way of fixing this is declaring your cookie as essential, so no matter what the consent check result is, your cookie will be sent over to the browser. To do this, change:

Response.Cookies.Append(
  "mykey",
  "myvalue",
  new CookieOptions()
  {
      Expires = DateTime.Now.AddMinutes(10)
  });

with

Response.Cookies.Append(
  "mykey",
  "myvalue",
  new CookieOptions()
  {
      Expires = DateTime.Now.AddMinutes(10),
      // Marking the cookie as essential
      IsEssential = true
  });
like image 119
Mickaël Derriey Avatar answered Nov 13 '22 15:11

Mickaël Derriey


I am Working with ASP.NET core 2.2. Here is what I have in my ConfigureServices(IServiceCollection services) to inject the HttpContextAccessor into my controller.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        //... some code
        //services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddHttpContextAccessor();
    }

Here is what I have in my controller:

    private readonly IHttpContextAccessor _httpContextAccessor;

    public MySomethingController(IHttpContextAccessor httpContextAccessor)
    {
        //... some code
        this._httpContextAccessor = httpContextAccessor;
    }

Here is the code for the Action method:

[HttpGet]
    public IActionResult SomethingToDo()
    {
        //... some code for my controller

        //Section for handling cookies
        //set the key value in Cookie  
        SetCookie("MyOwnKey", "Hello World from cookie", 15.0);

        //read cookie from IHttpContextAccessor 
        string cookieValueFromContext = _httpContextAccessor.HttpContext.Request.Cookies["MyOwnKey"];
        //or 
        string cookieValueFromRequest = GetCookie("MyOwnKey");

        //Delete the cookie object  
        //RemoveCookie("MyOwnKey");

        ViewData["CookieFromContext"] = cookieValueFromContext;
        ViewData["CookieFromRequest"] = cookieValueFromRequest;

        return View();
    }

Then I have the following methods:

    public string GetCookie(string key)
    {
        return Request.Cookies[key];
    }

    public void SetCookie(string key, string value, double? expireTime)
    {
        CookieOptions option = new CookieOptions();
        if (expireTime.HasValue)
            option.Expires = DateTime.Now.AddMinutes(expireTime.Value);
        else
            option.Expires = DateTime.Now.AddMilliseconds(1);
        Response.Cookies.Append(key, value, option);
    }

    public void RemoveCookie(string key)
    {
        Response.Cookies.Delete(key);
    }

I am able to see the cookie value in another controller and pass it to the view. I have this in the home controller:

...
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly IHostingEnvironment _hostingEnvironment;


    public HomeController(IHostingEnvironment hostingEnvironment, IHttpContextAccessor httpContextAccessor)
    {
        this._hostingEnvironment = hostingEnvironment;
        this._httpContextAccessor = httpContextAccessor;
    }

    public IActionResult Index()
    {
        //read cookie from IHttpContextAccessor 
        string cookieValueFromContext = _httpContextAccessor.HttpContext.Request.Cookies["MyOwnKey"];
        ViewData["CookieFromContext"] = cookieValueFromContext;

        return View();
    }

Good Luck

like image 30
Mario Levesque Avatar answered Nov 13 '22 14:11

Mario Levesque


A controller exposes HttpContext.Response.Cookies... There is no need to use dependency injection through the ConfigureServices method and there is no need to add the additional property to the controller. Just call HttpContext.Response.Cookies.Append(...);

like image 28
kevin james Avatar answered Nov 13 '22 14:11

kevin james