views:

922

answers:

4

I'm confused how CookieContainer handles domain, so I create this test. This test shows cookieContainer doesn't return any cookie for "site.com" but according to RFC it should return at least 2 cookies.

Isn't it a bug?

How make it to work?

Here is a discussion about this bug:

http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/c4edc965-2dc2-4724-8f08-68815cf1dce6

<%@ Page Language="C#" %>

<%@ Import Namespace="System.Net" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<script runat="server">
    CookieContainer getContainer()
    {
     CookieContainer result = new CookieContainer();

     Uri uri = new Uri("http://sub.site.com");
     string cookieH = @"Test1=val; domain=sub.site.com; path=/";
     result.SetCookies(uri, cookieH);

     cookieH = @"Test2=val; domain=.site.com; path=/";
     result.SetCookies(uri, cookieH);

     cookieH = @"Test3=val; domain=site.com; path=/";
     result.SetCookies(uri, cookieH);

     return result;
    }

    void Test()
    {
     CookieContainer cookie = getContainer();
     lblResult.Text += "<br>Total cookies count: " + cookie.Count + " &nbsp;&nbsp; expected: 3";

     Uri uri = new Uri("http://sub.site.com");
     CookieCollection coll = cookie.GetCookies(uri);
     lblResult.Text += "<br>For " + uri + " Cookie count: " + coll.Count + " &nbsp;&nbsp; expected: 2";

     uri = new Uri("http://other.site.com");
     coll = cookie.GetCookies(uri);
     lblResult.Text += "<br>For " + uri + " Cookie count: " + coll.Count + " &nbsp;&nbsp; expected: 2";

     uri = new Uri("http://site.com");
     coll = cookie.GetCookies(uri);
     lblResult.Text += "<br>For " + uri + " Cookie count: " + coll.Count + " &nbsp;&nbsp; expected: 2";

    }

    protected void Page_Load(object sender, EventArgs e)
    {
     Test();
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
    <title>CookieContainer Test Page</title>
</head>
<body>
    <form id="frmTest" runat="server">
    <asp:Label ID="lblResult" EnableViewState="false" runat="server"></asp:Label>
    </form>
</body>
</html>
+1  A: 

Here is a hack to get around this bug: http://social.microsoft.com/Forums/en-US/netfxnetcom/thread/1297afc1-12d4-4d75-8d3f-7563222d234c It uses reflection.

Salar
+3  A: 

Hi I just found the fix for this bug and discussed here: http://dot-net-expertise.blogspot.com/2009/10/cookiecontainer-domain-handling-bug-fix.html

Here the solution:

  1. Don't use .Add(Cookie), Use only .Add(Uri, Cookie) method.
  2. Call BugFix_CookieDomain each time you add a cookie to the container or before you use .GetCookie or before system use the container.

    private void BugFix_CookieDomain(CookieContainer cookieContainer)
    {
        System.Type _ContainerType = typeof(CookieContainer);
        Hashtable table = (Hashtable)_ContainerType.InvokeMember("m_domainTable",
                                   System.Reflection.BindingFlags.NonPublic |
                                   System.Reflection.BindingFlags.GetField |
                                   System.Reflection.BindingFlags.Instance,
                                   null,
                                   cookieContainer,
                                   new object[] { });
        ArrayList keys = new ArrayList(table.Keys);
        foreach (string keyObj in keys)
        {
            string key = (keyObj as string);
            if (key[0] == '.')
            {
                string newKey = key.Remove(0, 1);
                table[newKey] = table[keyObj];
            }
        }
    }
    

CallMeLaNN

CallMeLaNN
Thank you so much! I spent 2 days debugging this, thinking a newbie like me should learn to figure libraries on my own. But it was a bug!
PRINCESS FLUFF
Argh... where does _ContainerType come from? My compiler won't find it!
PRINCESS FLUFF
Ah! I found it... You need to replace _ContainerType by cookieContainer.GetType()
PRINCESS FLUFF
Just edit it to add System.Type _ContainerType = typeof(CookieContainer); Note that use this for faster performance. Using cookieContainer.GetType() each time will consume more time.
CallMeLaNN
It's this weird stuff that I hate microsoft for, though normally I don't mind them so much.It can happen when getting results form some domains, my.opera.com being one of them.
PintSizedCat
A: 

Visual Studio says: "The name '_ContainerType' does not exist in the current context" do I need to reference something?

hajovonta
He made a mistake, you need to replace _ContainerType by: cookieContainer.GetType()
PRINCESS FLUFF