For space saving reasons some parts of the .Net Framework are left out of the .Net Compact Framework. Unfortunately, (at least for me), one of the things not making the cut is the cookie support methods for the HttpWebRequest and HttpWebResponse classes. What this means is developers are left to handle cookies in their own code.
Cookies play an important role in web applications and sometimes your application will be required to read and/or set them. One of my applications Chronobis falls into this category. In order to authenticate to OWA servers using FORM based authentication, you must accept, store, and send cookies. The full version of the .Net Framework handles this almost seamlessly for you. However, in the Compact Framework you are on your own.
I decided to write an encapsulated CookieManager class to solve this problem for Chronobis, which I am providing here as an example of how to handle cookies in your .NET Compact Framework application.
Warning: This code assumes that every cookie stored will be sent. This means that I effectively ignore the cookie attribute values (Comment, Domain, Max-Age, Path, Secure, and Version). If your situation warrants, you might need to extend this code to account for them.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
namespace net.frejos.http
{
public class CookieManager
{
private Dictionary cookieValues;
public Dictionary CookieValues {
get {
if (this.cookieValues == null) {
this.cookieValues = new Dictionary();
}
return this.cookieValues;
}
}
public void PublishCookies(HttpWebRequest webRequest)
{
StringBuilder sb = new StringBuilder();
sb.Append("Cookie: ");
foreach (string key in this.CookieValues.Keys) {
sb.Append(key);
sb.Append("=");
sb.Append(this.CookieValues[key]);
sb.Append("; ");
sb.Append("$Path=\"/\"; ");
}
webRequest.Headers.Add(sb.ToString());
sb = null;
webRequest = null;
}
public void StoreCookies(HttpWebResponse webResponse)
{
for (int x=0; x < webResponse.Headers.Count; x++) {
if (webResponse.Headers.Keys[x].ToLower().Equals("set-cookie")) {
this.AddRawCookie( webResponse.Headers[x] );
}
}
webResponse = null;
}
private void AddRawCookie(string rawCookieData)
{
string key = null;
string value = null;
string[] entries = null;
if (rawCookieData.IndexOf(",") > 0)
{
entries = rawCookieData.Split(',');
}
else {
entries = new string[] { rawCookieData };
}
foreach (string entry in entries) {
string cookieData = entry.Trim();
if (cookieData.IndexOf(';') > 0)
{
string[] temp = cookieData.Split(';');
cookieData = temp[0];
}
int index = cookieData.IndexOf('=');
if (index > 0)
{
key = cookieData.Substring(0, index);
value = cookieData.Substring(index + 1);
}
if (key != null && value != null)
{
this.CookieValues[key] = value;
}
cookieData = null;
}
rawCookieData = null;
entries = null;
key = null;
value = null;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (string key in this.CookieValues.Keys) {
sb.Append("{");
sb.Append(key);
sb.Append(",");
sb.Append(this.CookieValues[key]);
sb.Append("}, ");
}
if (this.CookieValues.Keys.Count > 0)
{
sb.Remove(sb.Length - 2, 2);
}
sb.Append("]");
return sb.ToString();
}
}
}
A typical usage of this class would look something like this:
CookieManager cookieManager = new CookieManager();
// Set a cookie value
cookieManager.CookieValues["FavoriteCookie"] = "Chocolate Chip";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
// Publish the cookies to the request before asking for the response
cookieManager.PublishCookies(webRequest);
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
// Store any cookies returned from the response
cookieManager.StoreCookies(webResponse);
// Get the value of a cookie
string session = cookieManager.CookieValues["SESSIONID"];
webRequest = (HttpWebRequest)WebRequest.Create(url2);
cookieManager.PublishCookies(webRequest);
webResponse = (HttpWebResponse)webRequest.GetResponse();
Just in case you need a cookie RFC refresher, or need to add the missing functionality, you can find the RFC here.
The example source code contained within this post is provided under the terms of the MIT License. Copyright© 2008-2009 Joshua Freeman.
CookieManager.cs (3.39 kb)
0f8ac92e-7b7e-48a4-ad49-41b086d8c598|2|5.0