2013-04-13 38 views
16

我想用一个Newtonsoft.Json到的CookieContainer导出到JSON可惜的CookieContainer具有不枚举或东西,所以我可以通过它不是循环...如何获取CookieContainer的所有Cookie?

编辑:随着我发布的解决方案它会是这样的:

private static void Main(string[] args) 
{ 
    CookieContainer cookieContainer = new CookieContainer(); 
    cookieContainer.Add(new Cookie("name1", "value1", "/", ".testdomain1.com")); 
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/", ".testdomain1.com")); 
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/path2/", ".testdomain1.com")); 
    cookieContainer.Add(new Cookie("name1", "value1", "/", ".testdomain2.com")); 
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/", ".testdomain2.com")); 
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/path2/", ".testdomain2.com")); 

    CookieCollection cookies = GetAllCookies(cookieContainer); 

    Console.WriteLine(JsonConvert.SerializeObject(cookies, Formatting.Indented)); 
    Console.Read(); 
} 
+1

我不认为有除了使用反射来访问CookieContainer的私人领域(我不建议)以外所有cookie的方法。您应该将Cookie分开存储,并在需要时将其放入CookieContainer中。 – Will

回答

15

溶液使用反射:

public static CookieCollection GetAllCookies(CookieContainer cookieJar) 
{ 
    CookieCollection cookieCollection = new CookieCollection(); 

    Hashtable table = (Hashtable) cookieJar.GetType().InvokeMember("m_domainTable", 
                    BindingFlags.NonPublic | 
                    BindingFlags.GetField | 
                    BindingFlags.Instance, 
                    null, 
                    cookieJar, 
                    new object[] {}); 

    foreach (var tableKey in table.Keys) 
    { 
     String str_tableKey = (string) tableKey; 

     if (str_tableKey[0] == '.') 
     { 
      str_tableKey = str_tableKey.Substring(1); 
     } 

     SortedList list = (SortedList) table[tableKey].GetType().InvokeMember("m_list", 
                    BindingFlags.NonPublic | 
                    BindingFlags.GetField | 
                    BindingFlags.Instance, 
                    null, 
                    table[tableKey], 
                    new object[] { }); 

     foreach (var listKey in list.Keys) 
     { 
      String url = "https://" + str_tableKey + (string) listKey; 
      cookieCollection.Add(cookieJar.GetCookies(new Uri(url))); 
     } 
    } 

    return cookieCollection; 
} 
+0

此代码仅打印https cookie并忽略http。这里改进版本:http://stackoverflow.com/a/36665793/2010764 –

+0

我在http网站上使用这种方法。它工作正常,它会返回所有http cookie。但是,当我将https更改为http时,它不会打印所有的cookie,只有那些位于主域的cookie。 – Milad

6

第一个答案没有为便携式项目。因此,这里的选项2,还采用了反射

using System.Linq; 
using System.Collections; 
using System.Reflection; 
using System.Net; 

    public static CookieCollection GetAllCookies(this CookieContainer container) 
    { 
     var allCookies = new CookieCollection(); 
     var domainTableField = container.GetType().GetRuntimeFields().FirstOrDefault(x => x.Name == "m_domainTable");    
     var domains = (IDictionary)domainTableField.GetValue(container); 

     foreach (var val in domains.Values) 
     { 
      var type = val.GetType().GetRuntimeFields().First(x => x.Name == "m_list"); 
      var values = (IDictionary)type.GetValue(val); 
      foreach (CookieCollection cookies in values.Values) 
      { 
       allCookies.Add(cookies);      
      } 
     }   
     return allCookies; 
    } 

1)我也试过

var domainTableField = container.GetType().GetRuntimeField("m_domainTable"); 

但它返回null。

2)你可以通过domains.Keys遍历所有键并使用container.GetCookies()。但是我遇到了问题,因为GetCookies预计Uri并不是所有的密钥都与Uri模式匹配。

4

这种方法将确保让所有的cookies,无论该协议是什么:

public static IEnumerable<Cookie> GetAllCookies(this CookieContainer c) 
{ 
    Hashtable k = (Hashtable)c.GetType().GetField("m_domainTable", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(c); 
    foreach (DictionaryEntry element in k) 
    { 
     SortedList l = (SortedList)element.Value.GetType().GetField("m_list", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(element.Value); 
     foreach (var e in l) 
     { 
      var cl = (CookieCollection)((DictionaryEntry)e).Value; 
      foreach (Cookie fc in cl) 
      { 
       yield return fc; 
      } 
     } 
    } 
} 
0

使用CookieContainer.GetCookies Method

CookieCollection cookies = cookieContainer.GetCookies(new Uri(url)); 

其中url是您的网站的网址。

在我的情况下,我无法使用反射,正如其他答案中所建议的那样。但是,我确实知道我的网站的URL来查询。我认为容器不是盲目地返回所有的cookie,而是每个URL返回它们是合乎逻辑的,因为cookie总是属于特定的URL并且不能在与它们相关联的域的上下文之外使用。

+0

我不知道为什么其他作者需要反思和特殊的代码。 –

相关问题