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?
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.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With