web-dev-qa-db-fra.com

Comment puis-je obtenir tous les cookies d'un cookieContainer?

Je veux exporter un CookieContainer vers JSON à l'aide de Newtonsoft.Json mais malheureusement CookieContainer n'a pas d'énumérateur ni de trucs, donc je ne peux pas le parcourir ...

Edit: Avec ma solution publiée, ce serait quelque chose comme ceci:

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();
}
23
christophrus

Une solution par réflexion:

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;
}
19
christophrus

La première réponse n'a pas fonctionné pour un projet portable. Voici donc l'option 2, utilise également la réflexion

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) j'ai aussi essayé

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

mais il est retourné nul.

2) Vous pouvez parcourir les domaines.Keys et utiliser container.GetCookies () pour toutes les clés. Mais j'ai eu des problèmes avec cela, car GetCookies attend Uri et pas toutes mes clés correspondent au modèle Uri.

8
Ivan Popov

Cette méthode garantira d'obtenir tous les cookies, quel que soit le protocole:

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;
            }
        }
    }
}
8
Andre Andersen

Utilisez méthode CookieContainer.GetCookies

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

url est l'URL de votre site.

Dans mon cas, je n'ai pas pu utiliser la réflexion, comme suggéré dans d'autres réponses. Cependant, je connaissais l'URL de mon site à interroger. Je pense qu'il est même logique que le conteneur ne renvoie pas tous les cookies à l'aveugle mais les renvoie par URL car les cookies appartiennent toujours à une URL particulière et ne peuvent pas être utilisés en dehors du contexte du domaine qui leur est associé.

1
Boris Zinchenko