Cookies are text strings that is used within the browser memory. In reality, cookies can store anything, as long as you follow these limitations:
- Do not store more than 20 cookies per domain.
- Do not store more than 4096 bytes per cookie.
Microsoft states that their browser can store at least 20 cookies per domain and at least 4096 bytes per cookies, but the official max size is 4k, so you should stick to this.
With this in mind, my proposal to stream objects into a cookie is probably not such a good idea. There is some overhead when streaming classes in C#, as the class definitions are also stored. However, if you observe the limits as described above, you should be fine. The following piece of code saved me a lot of time, that’s for sure.
The first function will store a made-up class (called MyClass) into a cookie:
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Web; public void Store(MyClass myClass) { HttpCookie cookie = new HttpCookie("myCookie") { // Set the expiry date of the cookie to 15 years Expires = DateTime.Now.AddYears(15) }; Stream myStream = new MemoryStream(); try { // Create a binary formatter and serialize the // myClass into the memorystream IFormatter formatter = new BinaryFormatter(); formatter.Serialize(myStream, myClass); // Go to the beginning of the stream and // fill a byte array with the contents of the // memory stream myStream.Seek(0, SeekOrigin.Begin); byte[] buffer = new byte[myStream.Length]; myStream.Read(buffer, 0, (int)myStream.Length); // Store the buffer as a base64 string in the cookie cookie.Value = Convert.ToBase64String(buffer); // Add the cookie to the current http context HttpContext.Current.Response.Cookies.Add(cookie); } finally { // ... and remember to close the stream myStream.Close(); } }
One thing to remember is that cookies store strings, not binary data. That’s why I have to convert the stream to a byte array, and convert the byte array to a base 64 string. This conversion introduces another overhead as base64 strings converts 3 bytes into 4 ASCII chars.
Now lets restore my object from the cookie:
public MyClass Restore() { // Always remember to check that the cookie is not empty HttpCookie cookie = HttpContext.Current.Request.Cookies["myCookie"]; if (cookie != null) { // Convert the base64 string into a byte array byte[] buffer = Convert.FromBase64String(cookie.Value); // Create a memory stream from the byte array Stream myStream = new MemoryStream(buffer); try { // Create a binary formatter and deserialize the // contents of the memory stream into MyClass IFormatter formatter = new BinaryFormatter(); MyClass streamedClass = (MyClass)formatter.Deserialize(myStream); return streamedClass; } finally { // ... and as always, close the stream myStream.Close(); } } return null; }
If you replace the MyClass with an interface or a base class, you will have the flexibility to store any class either implementing the interface or inheriting from the base class.
And if you need help on how to remove cookies, you can read this article on how to add and remove cookies.
Brian,
A better way to do this would be to make your objects serializable, and then place the serialized “string” that represents your business object into the cookie.
LikeLike
Pingback: Storing a byte array in a Cookie (nom!) C# MVC | Jacqui's Technical Journal
Pingback: Storing a byte array in a Cookie (nom!) C# MVC – Jacqui.tk