考虑使用此标头的网络响应:
Set-Cookie: sample=testCookie; Domain=.sample.com; Expires=Tue, 25-Jan-2012 00:49:29 GMT; Path=/
此标头将映射到CookieCollection
中的.NET
。而且,当我们处理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
实现这一目标?
答案 0 :(得分:18)
我知道这已经得到了解答,但您可能希望使用此代码: 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的所有部分,包括名称,过期,路径,值和域。
答案 1 :(得分:12)
我认为您正在寻找CookieContainer。请参阅SetCookies方法。
答案 2 :(得分:3)
这是我用来执行此操作的扩展类。
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(',', ' ');
}
}
}