Check whether client’s browser have cookies enabled

Usually we assume that every user have cookies enabled. I cannot find any stats on the number of users who have disabled cookies, but 94% of all browsers have Javascript enabled, so lets assume that en equal number have cookies enabled (I know that the remaining 6% could easily be web crawlers).

What should we do with the remaining 6% then? If the website uses cookies as a shopping basket, it would be a good service to let the user know that he is not able to shop without enabling cookies.

When first investigatig this, I assumed that a server-side solution existed. So I implemented the following code in c#:

if (Request.Browser.Cookies) 
  Response.Write("Your browser supports cookies. You may shop");
else
  Response.Write("The Browser does not support Cookies. Shopping is not possible.");

Unfortunately this tells me if the browser as such supports cookies, not that cookies are enabled by the user. When using IE7, the code always returns true, since IE7 supports cookies in general. Disabling cookies in IE7 changes nothing.

I used Google to search for the answer, and unfortunately you need to use Javascript to check if the user have enabled cookies in his browser. This website contains the Javascript to use.

I rewrote the Javascript so it writes some text if cookies are enabled, and another text if not:

function CookieSetText(yesText, noText)
{
  var cookieEnabled=(navigator.cookieEnabled)? true : false
  //if not IE4+ nor NS6+
  if (typeof navigator.cookieEnabled=="undefined" && !cookieEnabled)
  {
    document.cookie="testcookie"
    cookieEnabled=(document.cookie.indexOf("testcookie")!=-1)? true : false
  }
  if (cookieEnabled)
    document.write(yesText);
  else
    document.write(noText);
}

 When adding a reference to the script in my HTML header, I can use it from my Sitecore XSLT’s:

<script type="text/javascript">
  CookieSetText('<sc:text field="CookiesEnabled"/>', '<sc:text field="CookiesDisabled"/>');
</script>

Th example above writes the text for the current item’s “CookiesEnabled” field if cookies are enabled, or writes from the “CookiesDisabled” field when cookies are disabled.

Streaming objects into a cookie

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.

Add and Remove cookies

Creating cookies is no problem:

// Create the cookie
HttpCookie cookie = new HttpCookie("MyCookie", "MyValue");
// Let the cookie expire in 1 year
cookie.Expires = DateTime.Now.AddYears(1);
// Add the cookie to the response header
HttpContext.Current.Response.Cookies.Add(cookie);

But have you ever tried to remove a cookie, but nothing happens? It seemes that the “Remove” have no effect:

//Why does this not remove my cookie?
HttpContext.Current.Request.Cookies.Remove("MyCookie");

Setting a cookie is a dialog between the client and server. Adding a cookie is done by adding it to the response header. It is the client (IE, FIrefox, Opera) who will write the cookie, usually to disk.

Next time the client requests a page from the domain, any un-expired cookies is written to the request headers, where you can read the information from within client side code.

Removing the cookie with Request.Cookies.Remove() only removes the cookie from the request collection, not from disk.

Instead you can let the cookie expire. The client will then leave the cookie when requesting a page from your domain:

// Find the cookie
HttpCookie cookie = HttpContext.Current.Request.Cookies["MyCookie"];
// If found, let the cookie expire
if (cookie != null)
  cookie.Expires = DateTime.Now.AddYears(-1);

Follow

Get every new post delivered to your Inbox.

Join 92 other followers