将标头cookie字符串映射到CookieCollection,反之亦然

考虑使用此标头的Web响应:

Set-Cookie: sample=testCookie; Domain=.sample.com; Expires=Tue, 25-Jan-2012 00:49:29 GMT; Path=/ 

此标头将映射到.NET CookieCollection 。 而且当我们处理CookieCollection它最终会转换为这样的header string

我正在寻找某种方式纯粹以两种方式进行这种转换。 当然, .NET在它的内部库中有它。 我相信任何从文本构造对象模型的类,反之亦然,应该支持两种方法(这里是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(); 

如何使用CookieCollection实现这一目标?

我想你正在寻找CookieContainer 。 请参见SetCookies方法。

我知道这已经得到了解答,但您可能想使用此代码: http : //snipplr.com/view/4427/

我在这里发布它,以防链接在某些时候出现故障:

 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) { strPNameAndPValue = strEachCookParts[j]; if (strPNameAndPValue != string.Empty) { NameValuePairTemp = strPNameAndPValue.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; } 

这段代码比微软自己的cookie解析器效果更好,这正是官方cookie解析器应该做的事情。 我没有任何线索,为什么微软还没有解决这个问题,因为这是一个非常普遍的问题。 它将读取逗号分隔的cookie,并正确解析每个cookie的所有部分,包括名称,过期,路径,值和域。

这是我用来做这个的扩展类。

 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(@"(?.*?)\=(?.*?)\;|(?\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 cookies) { cookies = new List(); 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 SplitToPair(this string input) { string[] parts= input.Split(new char[] {'='},StringSplitOptions.RemoveEmptyEntries); return new KeyValuePair(parts[0],parts[1]); } private static string RemoveComma(Match match) { return match.Value.Replace(',', ' '); } } }