Mapping Header cookie string to CookieCollection and vice versa
Consider a web response with this header:
Set-Cookie: sample=testCookie; Domain=.sample.com; Expires=Tue, 25-Jan-2012 00:49:29 GMT; Path=/
this header would be mapped to CookieCollection
in .NET
. And also when we deal with a CookieCollection
it will finally converted to such a header string
.
I'm looking some way to purely do this conversions in two way. Surely .NET
has it in it's internal library. I believe any class which constructs object model from text and vice versa should support two methods (here CookieCollection
):
// Creating cookie collection from header text
CookieCollection.TryParse(cookieHeaderString, out myCookieCollection);
// and getting the final header which would be sent by request
String cookieHeaderString = myCookieCollection.GetCookieHeaderString();
How can I achieve that with Coo开发者_开发问答kieCollection
?
I know that this has already been answered, but you might like to use this code: http://snipplr.com/view/4427/
I'm posting it here in case the link goes down at some point:
public static CookieCollection GetAllCookiesFromHeader(string strHeader, string strHost)
{
ArrayList al = new ArrayList();
CookieCollection cc = new CookieCollection();
if (strHeader != string.Empty)
{
al = ConvertCookieHeaderToArrayList(strHeader);
cc = ConvertCookieArraysToCookieCollection(al, strHost);
}
return cc;
}
private static ArrayList ConvertCookieHeaderToArrayList(string strCookHeader)
{
strCookHeader = strCookHeader.Replace("\r", "");
strCookHeader = strCookHeader.Replace("\n", "");
string[] strCookTemp = strCookHeader.Split(',');
ArrayList al = new ArrayList();
int i = 0;
int n = strCookTemp.Length;
while (i < n)
{
if (strCookTemp[i].IndexOf("expires=", StringComparison.OrdinalIgnoreCase) > 0)
{
al.Add(strCookTemp[i] + "," + strCookTemp[i + 1]);
i = i + 1;
}
else
{
al.Add(strCookTemp[i]);
}
i = i + 1;
}
return al;
}
private static CookieCollection ConvertCookieArraysToCookieCollection(ArrayList al, string strHost)
{
CookieCollection cc = new CookieCollection();
int alcount = al.Count;
string strEachCook;
string[] strEachCookParts;
for (int i = 0; i < alcount; i++)
{
strEachCook = al[i].ToString();
strEachCookParts = strEachCook.Split(';');
int intEachCookPartsCount = strEachCookParts.Length;
string strCNameAndCValue = string.Empty;
string strPNameAndPValue = string.Empty;
string strDNameAndDValue = string.Empty;
string[] NameValuePairTemp;
Cookie cookTemp = new Cookie();
for (int j = 0; j < intEachCookPartsCount; j++)
{
if (j == 0)
{
strCNameAndCValue = strEachCookParts[j];
if (strCNameAndCValue != string.Empty)
{
int firstEqual = strCNameAndCValue.IndexOf("=");
string firstName = strCNameAndCValue.Substring(0, firstEqual);
string allValue = strCNameAndCValue.Substring(firstEqual + 1, strCNameAndCValue.Length - (firstEqual + 1));
cookTemp.Name = firstName;
cookTemp.Value = allValue;
}
continue;
}
if (strEachCookParts[j].IndexOf("path", StringComparison.OrdinalIgnoreCase) >= 0)
{
strPNameAndPValue = strEachCookParts[j];
if (strPNameAndPValue != string.Empty)
{
NameValuePairTemp = strPNameAndPValue.Split('=');
if (NameValuePairTemp[1] != string.Empty)
{
cookTemp.Path = NameValuePairTemp[1];
}
else
{
cookTemp.Path = "/";
}
}
continue;
}
if (strEachCookParts[j].IndexOf("domain", StringComparison.OrdinalIgnoreCase) >= 0)
{
strDNameAndDValue = strEachCookParts[j];
if (strDNameAndDValue != string.Empty)
{
NameValuePairTemp = strDNameAndDValue.Split('=');
if (NameValuePairTemp[1] != string.Empty)
{
cookTemp.Domain = NameValuePairTemp[1];
}
else
{
cookTemp.Domain = strHost;
}
}
continue;
}
}
if (cookTemp.Path == string.Empty)
{
cookTemp.Path = "/";
}
if (cookTemp.Domain == string.Empty)
{
cookTemp.Domain = strHost;
}
cc.Add(cookTemp);
}
return cc;
}
This code will read in cookies that are comma separated and correctly parse all parts of each cookie including name, expiration, path, value, and domain.
I think you are looking for CookieContainer. See SetCookies method.
Here is my extension class I use to do this.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
namespace YourProjectName.Extensions
{
public static class HttpCookieExtension
{
static Regex rxCookieParts = new Regex(@"(?<name>.*?)\=(?<value>.*?)\;|(?<name>\bsecure\b|\bhttponly\b)", RegexOptions.Compiled |RegexOptions.Singleline|RegexOptions.IgnoreCase);
static Regex rxRemoveCommaFromDate = new Regex(@"\bexpires\b\=.*?(\;|$)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
public static bool GetHttpCookies(this NameValueCollection collection, int index , out List<HttpCookie> cookies)
{
cookies = new List<HttpCookie>();
if (collection.AllKeys[index].ToLower() != "set-cookie") return false;
try
{
string rawcookieString = rxRemoveCommaFromDate.Replace(collection[index], new MatchEvaluator(RemoveComma));
string[] rawCookies = rawcookieString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var rawCookie in rawCookies)
{
cookies.Add(rawCookie.ToHttpCookie());
}
return true;
}
catch (Exception)
{
return false;
}
}
public static bool GetHttpCookiesFromHeader(this string cookieHeader, out CookieCollection cookies)
{
cookies = new CookieCollection();
try
{
string rawcookieString = rxRemoveCommaFromDate.Replace(cookieHeader, new MatchEvaluator(RemoveComma));
string[] rawCookies = rawcookieString.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (rawCookies.Length == 0)
{
cookies.Add(rawcookieString.ToCookie());
}
else
{
foreach (var rawCookie in rawCookies)
{
cookies.Add(rawCookie.ToCookie());
}
}
return true;
}
catch (Exception)
{
throw;
}
}
public static Cookie ToCookie(this string rawCookie)
{
if (!rawCookie.EndsWith(";")) rawCookie += ";";
MatchCollection maches = rxCookieParts.Matches(rawCookie);
Cookie cookie = new Cookie(maches[0].Groups["name"].Value.Trim(), maches[0].Groups["value"].Value.Trim());
for (int i = 1; i < maches.Count; i++)
{
switch (maches[i].Groups["name"].Value.ToLower().Trim())
{
case "domain":
cookie.Domain = maches[i].Groups["value"].Value;
break;
case "expires":
DateTime dt;
if (DateTime.TryParse(maches[i].Groups["value"].Value, out dt))
{
cookie.Expires = dt;
}
else
{
cookie.Expires = DateTime.Now.AddDays(2);
}
break;
case "path":
cookie.Path = maches[i].Groups["value"].Value;
break;
case "secure":
cookie.Secure = true;
break;
case "httponly":
cookie.HttpOnly = true;
break;
}
}
return cookie;
}
public static HttpCookie ToHttpCookie(this string rawCookie)
{
MatchCollection maches = rxCookieParts.Matches(rawCookie);
HttpCookie cookie = new HttpCookie(maches[0].Groups["name"].Value, maches[0].Groups["value"].Value);
for (int i = 1; i < maches.Count; i++)
{
switch (maches[i].Groups["name"].Value.ToLower().Trim())
{
case "domain":
cookie.Domain = maches[i].Groups["value"].Value;
break;
case "expires":
DateTime dt;
if (DateTime.TryParse(maches[i].Groups["value"].Value, out dt))
{
cookie.Expires = dt;
}
else
{
cookie.Expires = DateTime.Now.AddDays(2);
}
break;
case "path":
cookie.Path = maches[i].Groups["value"].Value;
break;
case "secure":
cookie.Secure = true;
break;
case "httponly":
cookie.HttpOnly = true;
break;
}
}
return cookie;
}
private static KeyValuePair<string, string> SplitToPair(this string input)
{
string[] parts= input.Split(new char[] {'='},StringSplitOptions.RemoveEmptyEntries);
return new KeyValuePair<string, string>(parts[0],parts[1]);
}
private static string RemoveComma(Match match)
{
return match.Value.Replace(',', ' ');
}
}
}
精彩评论