5

I am developing an application that uses WebClient. I have this class that extends basic WebClient functionality:

public class WebClientEx : WebClient
{
    private CookieContainer _cookieContainer = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        if (request is HttpWebRequest)
        {
            (request as HttpWebRequest).CookieContainer = _cookieContainer;
            (request as HttpWebRequest).AllowAutoRedirect = true;
            (request as HttpWebRequest).Timeout = 10000;
        }
        return request;
    }
}

I use WebClientEx to login to site and to request some information. It works well for 4.0 and 4.5, but it doesn't work in earlier versions such as 3.5, 3.0 etc. I added some debug code and in early versions it says that there are 0 cookies in cookie container, while 4.0+ says that there are two cookies, as it should be.

So the reason is probably that early versions of .NET Framework have some problems with storing cookies in the cookie container. How to fix that?

Uhehesh
  • 506
  • 2
  • 8
  • 22
  • The answer to your question may be found here - http://stackoverflow.com/questions/1777221/using-cookiecontainer-with-webclient-class – dana Aug 20 '12 at 00:34
  • Anyone will help or I must use simpler solution without extending WebClient? – Uhehesh Aug 21 '12 at 19:01
  • 3
    My tests show this class is working as expected. Perhaps you could explain a little more as to why you believe it is not working. – dana Aug 21 '12 at 23:38

2 Answers2

5

I have confirmed the behaviour is different in .NET 3.5 compared to .NET 4.0. Is used the following code to test:

Uri sourceUri = new Uri(@"http://www.html-kit.com/tools/cookietester/");
WebClientEx webClientEx = new WebClientEx();
webClientEx.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
webClientEx.UploadString(sourceUri, "cn=MyCookieName&cv=MyCookieValue");
var text = webClientEx.DownloadString(sourceUri);
var doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(new MemoryStream(Encoding.ASCII.GetBytes((text))));
var node = doc.DocumentNode.SelectNodes("//div").Single(n => n.InnerText.StartsWith("\r\nNumber of cookies received:"));
Debug.Assert(int.Parse(node.InnerText.Split(' ')[4]) == 1);

Of course, this doesn't answer your question; but I can see no reason why there is a difference in behaviour other than to say maybe it was fixed in .NET 4.0 and the fix hasn't be put into .NET 3.5 or prior versions.

I tried a similar thing with HttpWebRequest and had the same problem (works in 4, but not prior):

HttpWebRequest webreq = ((HttpWebRequest) (WebRequest.Create(sourceUri)));
CookieContainer cookies = new CookieContainer();

var postdata = Encoding.ASCII.GetBytes("cn=MyCookieName&cv=MyCookieValue");

webreq.CookieContainer = cookies;
webreq.Method = "POST";
webreq.ContentLength = postdata.Length;
webreq.ContentType = "application/x-www-form-urlencoded";

Stream webstream = webreq.GetRequestStream();
webstream.Write(postdata, 0, postdata.Length);
webstream.Close();

using (WebResponse response = webreq.GetResponse())
{
    webstream = response.GetResponseStream();
    using (StreamReader reader = new StreamReader(webstream))
    {
        String responseFromServer = reader.ReadToEnd();
        var doc = new HtmlAgilityPack.HtmlDocument();
        doc.Load(new MemoryStream(Encoding.ASCII.GetBytes((responseFromServer))));
        var node =
            doc.DocumentNode.SelectNodes("//div").Single(n => n.InnerText.StartsWith("\r\nNumber of cookies received:"));
        Debug.Assert(int.Parse(node.InnerText.Split(' ')[4]) == 1);
    }
}

So, there seems to be a problem with HttpWebRequest (which WebClient uses). This might be new because I've seen people use code like this before 4.0 was released (maybe prior to 3.50 and they say it worked.

If it's urgent, I would suggest contacting Microsoft Support. If you have an MSDN license the following link will detail how to make a support request with the included MSDN support tickets: http://msdn.microsoft.com/en-us/subscriptions/bb266240.aspx If you don't have MSDN you can contact Support as detailed here: https://support.microsoft.com/oas/default.aspx?Gprid=8291&st=1&wfxredirect=1&sd=gn

if it's less urgent, then you could probably log the issue at http://connect.microsoft.com/VisualStudio to see if you get a response with workarounds.

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
  • Maybe I will just try other, simpler solution (so bad I should use bad solutions because of bugs). If I have spare time I will post a bug but I think they know about it. No one more will anser IMO so I will give you +50... – Uhehesh Aug 27 '12 at 18:29
2

I just created a basic IHttpHandler to test this class and it appears to work.

<%@ WebHandler Language="C#" Class="CookieTest" %>

using System;
using System.Net;
using System.Web;

public class CookieTest : IHttpHandler
{
    public class WebClientEx : WebClient
    {
        private CookieContainer _cookieContainer = new CookieContainer();

        protected override WebRequest GetWebRequest(Uri address)
        {
            WebRequest request = base.GetWebRequest(address);
            if (request is HttpWebRequest)
            {
                (request as HttpWebRequest).CookieContainer = _cookieContainer;
                (request as HttpWebRequest).AllowAutoRedirect = true;
                (request as HttpWebRequest).Timeout = 10000;
            }
            return request;
        }
    }

    public void ProcessRequest(HttpContext ctxt)
    {
        ctxt.Response.ContentType = "text/plain";

        String cmd = ctxt.Request["cmd"];
        if (cmd == "set")
        {
            ctxt.Response.Cookies.Add(new HttpCookie("test", "test"));
            ctxt.Response.Write("Cookie Set: test = test");
        }
        else if (cmd == "get")
        {
            ctxt.Response.Write("Cookie Value: test = " + ctxt.Request.Cookies["test"].Value);
        }
        else
        {
            // run out tests
            WebClientEx wc = new WebClientEx();

            ctxt.Response.Write("Running tests on .NET version: " + Environment.Version);
            ctxt.Response.Write(Environment.NewLine + Environment.NewLine);
            ctxt.Response.Write("Setting Cookie...");
            ctxt.Response.Write(Environment.NewLine + Environment.NewLine);
            ctxt.Response.Write("Response: " + wc.DownloadString(ctxt.Request.Url.AbsoluteUri + "?cmd=set"));
            ctxt.Response.Write(Environment.NewLine + Environment.NewLine);
            ctxt.Response.Write("Getting Cookie...");
            ctxt.Response.Write(Environment.NewLine + Environment.NewLine);
            ctxt.Response.Write("Response: " + wc.DownloadString(ctxt.Request.Url.AbsoluteUri + "?cmd=get"));
            ctxt.Response.Write(Environment.NewLine + Environment.NewLine);
        }
    }

    public bool IsReusable
    {
        get { return true; }
    }
}

The results I get are:

Running tests on .NET version: 2.0.50727.5456

Setting Cookie...

Response: Cookie Set: test = test

Getting Cookie...

Response: Cookie Value: test = test

Does this seem correct to you?

dana
  • 17,267
  • 6
  • 64
  • 88
  • I am going to test that now. Probably the problem is my project settings. – Uhehesh Aug 21 '12 at 23:50
  • Your code didn't help me at all, because it is ASP.NET code, and I have just C# for Windows. I tried to make project again and import code to it, but the result is all the same. – Uhehesh Aug 22 '12 at 00:12
  • @Uhehesh - The reason I used ASP.NET is because I was able to implement both (a) client and (b) server in a small amount of code. I could walk you through how to set this up on your machine if you are interested. However I was wondering if you could provide more details as to what testing / debugging you did that makes you think this class does not work. – dana Aug 22 '12 at 15:54
  • OK, I understand this. But as I said, I have added some code for debug, and it said that there are 0 cookies on GetWebRequest in 1.0-3.5, while it said 2 cookies (as it should be) in 4.0 and 4.5. – Uhehesh Aug 22 '12 at 17:07
  • 1
    If you are unable to provide more details regarding how you are testing your code (maybe a sample of how you are using it) I unfortunately cannot be of more assistance. Sorry. – dana Aug 22 '12 at 17:14