How can I get all Cookies of a CookieContainer?
Asked Answered
F

4

29

I want to export a CookieContainer to JSON using Newtonsoft.Json but unfortunately CookieContainer hasn't an enumerator or stuff, so I can't cycle through it ...

Edit: With my posted solution it would be something like this:

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();
}
Frenchman answered 13/4, 2013 at 1:21 Comment(1)
I don't think there is a way to get all the cookies besides using reflection to access CookieContainer's private fields(I don't recommend). You should just store the cookies separately and put them into a CookieContainer when you need to.Rawls
F
26

A solution using reflection:

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

.NET 6 Update

Finally, .NET 6 was released and introduced the CookieContainer.GetAllCookies() method which extracts the CookieCollection - Documentation link.

public System.Net.CookieCollection GetAllCookies();
Frenchman answered 13/4, 2013 at 18:1 Comment(2)
This code only prints https cookies and ignore http. Improved version here: https://mcmap.net/q/501907/-how-to-get-cookies-info-inside-of-a-cookiecontainer-all-of-them-not-for-a-specific-domainPapa
I'm using this method on a http web site. It works fine and it returns all http cookies. But when I change https to http it does not print all of cookies, only those which are on main domain.Gulosity
O
19

This method will ensure to get all cookies, no matter what the protocol is:

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;
            }
        }
    }
}
Osrock answered 9/8, 2015 at 3:42 Comment(0)
Z
10

The first answer did not work for a portable project. So here's option 2, also uses reflection

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) I also tried

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

but it returned null.

2) You can iterate through domains.Keys and use container.GetCookies() for all keys. But I've had problems with that, because GetCookies expects Uri and not all my keys matched Uri pattern.

Zebe answered 6/5, 2015 at 15:10 Comment(0)
S
-3

Use CookieContainer.GetCookies Method

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

where url is URL of your site.

In my case, I was not able to use reflection, as suggested in other answers. However, I did know URL of my site to query. I think it is even logical that container does not return all cookies blindly but returns them per URL because cookies always belong to a particular URL and cannot be used outside of context of the domain associated with them.

Sedimentary answered 25/1, 2018 at 14:12 Comment(2)
I m not sure why other authors needed reflection and special code.Sedimentary
The OP wants a list of all cookies, ~regardless of the url/Uri. That is the difference.Kc

© 2022 - 2024 — McMap. All rights reserved.