I'm using cookies to display some data in a search page but my cookies are garbling the values when using Unicode characters. For example when I store Inglês
, I'm getting Inglês
when I read it back.
This is how I save my cookie:
public void SalvaValue(string sessionKey, string sessionValue)
{
Response.Cookies.Add(new HttpCookie(sessionKey));
var httpCookie = Response.Cookies[sessionKey];
if (httpCookie != null) httpCookie.Value = sessionValue;
if (httpCookie != null) httpCookie.Expires = DateTime.Now.AddDays(14);
}
This is how I retrieve it:
if (Request.Cookies["BuscaTipo"] != null)
{
tipoBusca = Request.Cookies["BuscaTipo"].Value.ToString();
var cookie = new HttpCookie("BuscaTipo") { Expires = DateTime.Now.AddDays(-1) };
Response.Cookies.Add(cookie);
}
When I debug the site, it shows the right value in code when setting it, but after I perform a request with jQuery, the value comes up with the wrong characters.
How can I safely store Unicode characters in cookies?
According to the standards of the Internet Engineering Task Force (IETF), the institution responsible for documenting standards used on the Internet, cookies cannot have special characters in their composition, including non-ASCII characters.
A cookie definition begins with a name-value pair. A <cookie-name> can contain any US-ASCII characters except for: the control character, space, or a tab. It also must not contain separator characters like the following: ( ) < > @ , ; : \ " / [ ] ?
Data types nchar, nvarchar, and long nvarchar are used to store Unicode data. They behave similarly to char, varchar, and long varchar character types respectively, except that each character in a Unicode type typically uses 16 bits.
Simply enter your data then push the encode button. To encode binaries (like images, documents, etc.)
See How to store other languages (unicode) in cookies and get it back again, Unicode Cookie Value, How to send non-English unicode string using HTTP header? and Allowed characters in cookies for an explanation why you need to encode cookie values.
In short: Unicode characters in headers (in which cookies are sent) are supported by most browsers, but not all. Some browsers interpret the Unicode bytes as ASCII, resulting in Mojibake.
jQuery also seems to play a role according to some of the linked questions, but I cannot reproduce that.
Therefore to safely store Unicode characters (or rather any non-ASCII or control characters) across all browsers, you need to encode the characters. This can be implemented through, for example, base64 and percent-encoding.
An implementation of the latter, slightly adapted from Cookies and Unicode characters:
public static class CookieExtensions
{
public static string DecodedValue(this HttpCookie cookie)
{
if (cookie == null)
{
throw new ArgumentNullException("cookie");
}
return HttpUtility.UrlDecode(cookie.Value);
}
public static void SetEncodedValue(this HttpCookie cookie, string value)
{
if (cookie == null)
{
throw new ArgumentNullException("cookie");
}
cookie.Value = HttpUtility.UrlEncode(value);
}
public static string DecodedValues(this HttpCookie cookie, string name)
{
if (cookie == null)
{
throw new ArgumentNullException("cookie");
}
return HttpUtility.UrlDecode(cookie.Values[name]);
}
public static void SetEncodedValues(this HttpCookie cookie, string name, string value)
{
if (cookie == null)
{
throw new ArgumentNullException("cookie");
}
cookie.Values[name] = HttpUtility.UrlEncode(value);
}
public static string DecodedValues(this HttpCookie cookie, int index)
{
if (cookie == null)
{
throw new ArgumentNullException("cookie");
}
return HttpUtility.UrlDecode(cookie.Values[index]);
}
}
Usage:
if (Request.Cookies["TestCookieValue"] != null)
{
ViewBag.CookieValue = Request.Cookies["TestCookieValue"].DecodedValue();
}
if (Request.Cookies["TestCookieValues"] != null)
{
ViewBag.CookieValues = Request.Cookies["TestCookieValues"].DecodedValues("foo");
ViewBag.CookieValuesIndexed = Request.Cookies["TestCookieValues"].DecodedValues(0);
}
var cookieWithValue = new HttpCookie("TestCookieValue");
cookieWithValue.Expires = DateTime.Now.AddHours(1);
cookieWithValue.SetEncodedValue("Inglês");
Response.SetCookie(cookieWithValue);
var cookieWithValues = new HttpCookie("TestCookieValues");
cookieWithValues.Expires = DateTime.Now.AddHours(1);
cookieWithValues.SetEncodedValues("foo", "Inglês");
Response.SetCookie(cookieWithValues);
Please note HttpUtility.UrlDecode()
is dangerous, use AntiXSS to prevent Cross-site Scripting and SQL injection from the cookie values, which can be arbitrarily set by the client.
You may also perhaps reconsider storing Unicode values in cookies. You can easily identify the language otherwise, for example through the code en-US
or its database index if applicable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With