2013-04-13 14 views
16

chcę wyeksportować CookieContainer do JSON przy użyciu Newtonsoft.Json ale niestety CookieContainer nie ma wyliczający lub rzeczy, więc nie mogę przez niego cykl ...Jak mogę uzyskać wszystkie pliki cookie CookieContainer?

Edit: Z moim pisał rozwiązaniem byłoby być coś takiego:

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

Nie sądzę, że istnieje sposób, aby uzyskać wszystkie pliki cookie oprócz korzystania z refleksji, aby uzyskać dostęp do prywatnych pól CookieContainer (nie polecam). Powinieneś po prostu przechowywać pliki cookie osobno i umieścić je w CookieContainer, kiedy zajdzie taka potrzeba. – Will

Odpowiedz

15

roztwór stosując odbicie:

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

Ten kod wypisuje tylko pliki cookie https i ignoruje http. Ulepszona wersja tutaj: http://stackoverflow.com/a/36665793/2010764 –

+0

Używam tej metody na stronie http. Działa dobrze i zwraca wszystkie pliki cookie http. Ale kiedy zmienię https na http, nie wydrukuje wszystkich plików cookie, tylko te, które są w głównej domenie. – Milad

6

pierwsza odpowiedź nie działa dla przenośnego projektu. Tak tu jest opcja 2, wykorzystuje również odbicie

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) Próbowałem też

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

ale wrócił zerowa.

2) Możesz iterować przez domeny. Klawisze i użyj container.GetCookies() dla wszystkich kluczy. Ale miałem z tym problemy, ponieważ GetCookies spodziewa się, że Uri i nie wszystkie moje klucze pasują do wzoru Uri.

4

Metoda ta zapewni, aby wszystkie pliki cookie, bez względu na protokół:

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

Korzystając CookieContainer.GetCookies Method

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

gdzie url jest adres URL witryny.

W moim przypadku nie byłem w stanie skorzystać z refleksji, jak sugerowano w innych odpowiedziach. Jednak znałem adres URL mojej strony do zapytania. Myślę, że logiczne jest, że kontener nie zwraca wszystkich plików cookie na ślepo, ale zwraca je na adres URL, ponieważ pliki cookie zawsze należą do konkretnego adresu URL i nie mogą być używane poza kontekstem związanej z nimi domeny.

+0

Nie jestem pewien, dlaczego inni autorzy potrzebowali refleksji i specjalnego kodu. –

Powiązane problemy