For a comparison of various ASP.NET state management techniques (including cookies) and their inherit advantages and disadvantages, see my previous post – Managing State in ASP.NET – which bag to use and when. This post covers the purely technical side of dealing with cookies in ASP.NET
I’m glad the ASP.NET team gave us access as raw as they did, but it also means that you need to have an understanding of how cookies work before you use them. As much as it might seem, you can’t just jump in and use them straight away.
First of all, you need to understand how they are stored and communicated. Cookies are stored on the user’s local machine, actually on their hard-drive. Every time the browser performs a request, it sends the relevant cookies up with the request. The server can then send cookies back with the response, and these are saved or updated on the client accordingly.
Now you need to remember that cookies are uploaded with every request, so don’t go storing anything too big in there particularly as most users have uplinks which are much slower than their downlinks. With this in mind, you should generally try and just store an id in the cookie and persist the actually data in a database on the server or something like that.
Finally, you only need to send cookies that have changed back with the response, somewhat like a delta. This introduces some intricacies, like “how do you delete a cookie” which I’ll discuss in a sec.
The Request.Cookies bag is writeable, but don’t let that deceive you. Adding cookies here isn’t going to help you, because this is just the upload side. To create a new cookie, we need to add it to the Response.Cookies bag. This is the bag that is written back to the client with the page, and thus it plays the role of our “diff”.
The HttpCookie constructor exposes very simple name and value properties:
To get some real control over your cookies though, take a look at the properties on the HttpCookie before you call Response.Cookies.Add.
- Domain lets you restrict cookie access to a particular domain.
- Expires sets the absolute expiry date of the cookie as a point in time. You can’t actually create a cookie which lives indefinitely, so if that’s what you’re trying to achieve just set it to DateTime.UtcNow.AddYears(50).
- Path lets you restrict cookie access to a particular request path.
- Secure lets you restrict cookie access to HTTPS requests only.
If a cookie is not accessible to a request, it will just not be uploaded with the request and the server will never know it even existed.
Any cookie that exists in Response.Cookies will get sent back to the client. The browser will then save each of those cookies, and override any cookies that have the same key and belong to the same domain, path, etc.
This means that to update the value of a cookie, you actually have to create a whole new cookie in the Response.Cookies collection that will then override the original value.
Updating the value of cookies is rare though, because as suggested early you should only be aiming to save an id in the cookie, and ids don’t generally have to change.
As with updating, this is rare, but sometime you gotta do it.
We know that we only have to send back cookies that we want to update, so how do we delete a cookie? Not specifying it in the response just tells the browser it hasn’t changed.
Well, this is fun. 🙂
Create a new cookie in the Response.Cookies bag with the same key as the one you are trying to delete, then set the expiry date of this cookie to be in the past. When the client browser attempts to save the cookie it will override what was there with an expired cookie, thus effectively deleting the original cookie.
Remember that your user’s time maybe offset from your servers, so play it safe and set the expiry date to at least DateTime.Now.AddHours(-24);