0

This is how I am setting my cookie in my controller. When I navigate to the About function, I get this error:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

Microsoft.AspNetCore.Http.IRequestCookieCollection.this[string].get returned null

Is this the correct way to set a cookie after I login or authenticate my user? .

public IActionResult Index()
{
    LoginViewModel lvm = new LoginViewModel
    {
        Email = "login@app.com",
        Password = "Password"
    };
    var result = authenticationClient.Authenticate(lvm);
    Response.Cookies.Append("Token", result.Token);
    Response.Cookies.Append("RefreshToken", result.RefreshToken);
    return View();
}

public IActionResult About()
{
    ViewData["Message"] = "Your application description page.";
    ViewBag.Message = GetCookieValueFromResponse(Response, "Token");

    return View();
}

Also, is it possible to create a reusable generic class to set a cookie and read it?

This is not a duplicate just because it has a null exception. I have tried this method to retrieve my cookie but it just returns null?

    string GetCookieValueFromResponse(HttpResponse response, string cookieName)
    {
        foreach (var headers in response.Headers)
        {
            if (headers.Key != "Set-Cookie")
                continue;
            string header = headers.Value;
            if (header.StartsWith($"{cookieName}="))
            {
                var p1 = header.IndexOf('=');
                var p2 = header.IndexOf(';');
                return header.Substring(p1 + 1, p2 - p1 - 1);
            }
        }
        return null;
    }
JianYA
  • 2,402
  • 3
  • 36
  • 89

1 Answers1

0

You normally do not read cookies from the response but from your request:

  • Server adds cookie to response
  • Browser reads cookie from response and saves it
  • Browser sends cookie with next request
  • Server can read Cookies from request

Problem: You're trying to read in your GetCookieValueFromResponse() function the "Set-Cookie IN BROWSER" header. This would work in you Index() action because you added the cookie before to your response. It will not work in your About() action.

In your About() action you can read the cookie from the Request object:

 Request.Cookies[cookieName]

In the previous version of your question you had the following code in your your About action:

// will throw NPE if cookie is not set
Request.Cookies["mycookie"].ToString()

Problem: If you cookie is not available, it will be null so you're calling ToString() on null. Solution: remove ToString(). It makes no sense because a cookie value is always a string already.

How to check where's the problem:

  • Check if your browser has stored the cookie after opening your Index() action.
  • If not: Check if response of Index() action contains Set-Cookie header
  • If yes: Check if request to About() contains Cookie (NOT Set-Cookie) header
  • If not: Check cookie options (path,... ?)
  • If yes: It should be available in Request.Cookies now ;-)

Do all these checks in your browser's developer tools.

If your cookie was not set (not visible in browser and no set-cookie header in response), check GDPR settings in Startup.cs. If CheckConsentNeeded is set to true, aps core will not send Set-Cookie headers for most cookies. For details: https://docs.microsoft.com/en-us/aspnet/core/security/gdpr?view=aspnetcore-2.1

Christoph Lütjen
  • 3,750
  • 18
  • 26