5

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?}");
        });
    }
}
Ahmad Javadi Nezhad
  • 527
  • 1
  • 5
  • 23

3 Answers3

8

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
  });
Mickaël Derriey
  • 12,796
  • 1
  • 53
  • 57
  • I applied both ways but didn't work for me, can you please let me know how to store cookie and startup class –  Dec 12 '18 at 17:19
1

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

Mario Levesque
  • 1,017
  • 13
  • 13
  • Could you please tell us how to update a cookie's value? Should I delete it first and then set it again? – Anastasios Moraitis Aug 13 '19 at 18:18
  • 1
    @Anastasios Moraitis you may have to delete and add. I have not tried but intellisense only shows me Append, Delete, Equals, GetHashCode, GetType and ToString for its methods. Please note that the cookie has value but also might have an expiration. By "updating" you may want to replace the value, or the expiration or both. – Mario Levesque Aug 14 '19 at 20:11
1

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