Tech Off Thread

13 posts

Bug in CookieContainer, where do I report?

Back to Forum: Tech Off
  • User profile image
    JohnWinner

    Sometimes I cannot retrieve cookies from the CookieContainer. The problem is in the way the class sets cookies or in the way it retrieves those cookies. Either way, the class is so restricted that I didn't find any workaround.

    Is there an official place to post the bug?

    Here is some simple lines to replicate the bug:

    Uri uri = new Uri(http://my.opera.com/);

    //using CookieContainer.Add
    CookieContainer cc = new CookieContainer();
    Cookie c = new Cookie("opera_test", "12345", "/", "my.opera.com");
    cc.Add(c);
    Console.Write(cc.GetCookies(uri).Count); //Works!

    //using CookieContainer.SetCookies
    cc = new CookieContainer();
    cc.SetCookies(uri,
    "opera_test=12345;path=/;domain=my.opera.com");
    Console.Write(cc.GetCookies(uri).Count); //Doesn't work!? CookieContainer.Count shows 1 cookie but where is it? Cannot retrieve it using any variant of opera uri.

    Any help appreciated.
    Thanks!

  • User profile image
    dmshann0n

    I had a similar issue, and this was of some help.

    The issue arises because the CookieCollection contained in the CookieContainer is selected based on the base Uri (Authority portion), but it is entered in some cases as the entire Uri of the original request. If you inspect the CookieContainer at run-time, you can see that the internal "m_domainTable" contains these Uri values.

    To resolve the issue, I added the following lines after I get the ResponseStream (when the CookieContainer is populated):

    foreach ( Cookie c in cookies.GetCookies ( request.Address ) )
        cookies.Add ( new Uri ( request.Address.GetLeftPart(UriPartial.Authority)), c );

    The "cookies" variable is the CookieContainer set to the "CookieContainer" property of the HttpWebRequest. There is probably some work to remove the old cookies, because I am now doubling up the original cookies sent. As of yet, this isn't an issue for my throw away application.

  • User profile image
    stevo_

    Well, this line;

    cc.SetCookies(uri, "opera_test=12345;path=/;domain=my.opera.com");

    I could be off the mark here but the Uri provided should be stating the domain of the cookie anyway.. it seems to me that SetCookies allows you to provide a domain base (in Uri form), and a collection of cookies in value form.. I imagine the parser will set the domain on the cookies from the Uri..

    Soo, this would work?;

    cc.SetCookies(uri, "opera_test=12345;path=/");

  • User profile image
    stevo_

    blehbleh wrote:
    Hmmm !!! I wonder if this is the "problem" which I have ?
    (
    http://channel9.msdn.com/ShowPost.aspx?PostID=370427 ) Could it actually be a bug?


    And no, it's not the same.. your bug is probably related to cookies with no value (i.e., the cookie isn't null but its value is) or sync problems with the response and request collections..

  • User profile image
    JChung2006

    You may want to use Fiddler or some other HTTP sniffing tool to see if the two bits of code you have above send the same HTTP set-cookie command or not.  RFC 2109 indicates that you should prepend your Path and Domain names with $.

    The following works:

    cc = new CookieContainer();
    cc.SetCookies(uri, "opera_test=12345; $Path=/; $Domain=my.opera.com");
    Console.Write(cc.GetCookies(uri).Count);
    
  • User profile image
    JohnWinner

    Thanks for your help guys.

    I don't have any control on the way cookies are passed to my program. I have to "screenscrape" a lot of sites for one of my project and sometimes Apache and/or IIS send cookies and the CookieContainer doesn't preserve those cookies.

    I tell you this after countless hours of HTTP sniffing / debugging / testing.

    I had to implement my own cookiecontainer with some custom WebRequest and WebResponse objects. A nightmare!

  • User profile image
    JohnWinner

    By the way, is there any way to hack into a .NET class and add some code?

    A few lines in the CookieContainer class and everything would be fine.

  • User profile image
    atanamir

    There is also a problem with getting cookies out of a container too when the domain begins with a .:

    CookieContainer
    container = new CookieContainer();
    container.Add(
    new Cookie("x", "1", "/", ".blah.com"));
    CookieCollection cv = container.GetCookies(new Uri("http://blah.com"));
    cv = container.GetCookies(
    new Uri("http://w.blah.com"));

    The first GetCookies returns 0 when its supposed to be 1.
    the second one will return 1.

    Any ideas?

    Thanks
    Stephen

  • User profile image
    NathanRidley

    atanamir said:
    There is also a problem with getting cookies out of a container too when the domain begins with a .:

    CookieContainer
    container = new CookieContainer();
    container.Add(
    new Cookie("x", "1", "/", ".blah.com"));
    CookieCollection cv = container.GetCookies(new Uri("http://blah.com"));
    cv = container.GetCookies(
    new Uri("http://w.blah.com"));

    The first GetCookies returns 0 when its supposed to be 1.
    the second one will return 1.

    Any ideas?

    Thanks
    Stephen
    Did you ever find a workaround for this issue? I've just hit it myself. Your comment and one other page on Google reporting the same issue (without any replies) were the only mentions of the issue I could find after about 3 hours of searching Google.

    I suspect I'm going to have to do some fancy reprocessing of the cookie container contents to work around the problem. Very annoying. It would be nice if the CookieContainer class was overridable, but alas it is not to be...

  • User profile image
    JohnWinner

    NathanRidley said:
    atanamir said:
    *snip*
    Did you ever find a workaround for this issue? I've just hit it myself. Your comment and one other page on Google reporting the same issue (without any replies) were the only mentions of the issue I could find after about 3 hours of searching Google.

    I suspect I'm going to have to do some fancy reprocessing of the cookie container contents to work around the problem. Very annoying. It would be nice if the CookieContainer class was overridable, but alas it is not to be...
    The cookiecontainer is still buggy. The worst is that even if you write a new CookieContainer class you cannot override the current HttpRequest and response cookiecontainer, you also need to write your own request and response.  If only we can just access all the cookies in CookieContainer using a simple foreach.
    Please MICROSOFT!

  • User profile image
    JohnWinner

    I found a hack to list all the cookies of all URI in a CookieContainer.  (Inspired from this post)
    Very useful to track down bugs and to "fix" cookies.

    public List<Cookie> GetAllCookies(CookieContainer cc)
            {
                List<Cookie> lstCookies = new List<Cookie>();

                Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cc, new object[] { });
               
                foreach (var pathList in table.Values)
                {
                    SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, pathList, new object[] { });
                    foreach (CookieCollection colCookies in lstCookieCol.Values)
                        foreach (Cookie c in colCookies) lstCookies.Add(c);
                }
               
                return lstCookies;
            }
            public string ShowAllCookies(CookieContainer cc)
            {
                StringBuilder sb = new StringBuilder();
                List<Cookie> lstCookies = GetAllCookies(cc);
                sb.AppendLine("=========================================================== ");
                sb.AppendLine(lstCookies.Count + " cookies found.");
                sb.AppendLine("=========================================================== ");
                int cpt = 1;
                foreach (Cookie c in lstCookies)
                    sb.AppendLine("#" + cpt++ + "> Name: " + c.Name + "\tValue: " + c.Value + "\tDomain: " + c.Domain + "\tPath: " + c.Path + "\tExp: " + c.Expires.ToString());
               
                return sb.ToString();
            }

  • User profile image
    DCutts

    JohnWinner said:
    I found a hack to list all the cookies of all URI in a CookieContainer.  (Inspired from this post)
    Very useful to track down bugs and to "fix" cookies.

    public List<Cookie> GetAllCookies(CookieContainer cc)
            {
                List<Cookie> lstCookies = new List<Cookie>();

                Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cc, new object[] { });
               
                foreach (var pathList in table.Values)
                {
                    SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, pathList, new object[] { });
                    foreach (CookieCollection colCookies in lstCookieCol.Values)
                        foreach (Cookie c in colCookies) lstCookies.Add(c);
                }
               
                return lstCookies;
            }
            public string ShowAllCookies(CookieContainer cc)
            {
                StringBuilder sb = new StringBuilder();
                List<Cookie> lstCookies = GetAllCookies(cc);
                sb.AppendLine("=========================================================== ");
                sb.AppendLine(lstCookies.Count + " cookies found.");
                sb.AppendLine("=========================================================== ");
                int cpt = 1;
                foreach (Cookie c in lstCookies)
                    sb.AppendLine("#" + cpt++ + "> Name: " + c.Name + "\tValue: " + c.Value + "\tDomain: " + c.Domain + "\tPath: " + c.Path + "\tExp: " + c.Expires.ToString());
               
                return sb.ToString();
            }

    i also had to read the cookie container into a cookie collection and then loop through all cookies in the cookie collection.

    Dim retString as String = ""
    Dim cCol As New CookieCollection

    cCol.Add(wRequest.CookieContainer.GetCookies(wRequest.GetResponse.ResponseUri))


    For i As Integer = 0 To cCol.Count - 1
    retString += cCol.Item(i).Name & "=" & cCol.Item(i).Value
    Next

  • User profile image
    checker

    I added another feedback about backport this issue to .NET 2.0-3.5
    https://connect.microsoft.com/VisualStudio/feedback/details/541197/cookiecontainer-domain-handling-issue-net-2-0-3-5
    If anybody interested as well you can vote for it

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.