WebClient CookieContainer在.NET 4.0+中运行良好,但在早期版本中运行不佳

时间:2012-08-19 20:33:32

标签: c# .net webclient

我正在开发一个使用WebClient的应用程序。我有这个类扩展了基本的WebClient功能:

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

我使用WebClientEx登录网站并请求一些信息。它适用于4.0和4.5,但它不适用于早期版本,如3.5,3.0等。我添加了一些调试代码,在早期版本中,它说cookie容器中有0个cookie,而4.0+表示那里是两个饼干,应该是。

因此,原因可能是早期版本的.NET Framework存在将cookie存储在cookie容器中的一些问题。如何解决?

2 个答案:

答案 0 :(得分:5)

我已经确认.NET 3.5与.NET 4.0相比,行为有所不同。使用以下代码进行测试:

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

当然,这不能回答你的问题;但我没有理由认为行为存在差异,除了说它可能已经在.NET 4.0中得到修复,并且修复版没有放入.NET 3.5或之前的版本中。

我尝试了与HttpWebRequest类似的问题并遇到了同样的问题(在4中工作,但不是在之前):

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

因此,HttpWebRequest似乎存在问题(WebClient使用)。这可能是新的,因为我看到人们在4.0发布之前使用这样的代码(可能在3.50之前,他们说它有效。

如果紧急,我建议您与Microsoft支持部门联系。如果您拥有MSDN许可证,则以下链接将详细说明如何使用随附的MSDN支持服务单发出支持请求:http://msdn.microsoft.com/en-us/subscriptions/bb266240.aspx如果您没有MSDN,可以按照此处的详细信息联系支持部门:https://support.microsoft.com/oas/default.aspx?Gprid=8291&st=1&wfxredirect=1&sd=gn < / p>

如果不那么紧急,那么你可以在http://connect.microsoft.com/VisualStudio上记录问题,看看你是否得到了解决方法。

答案 1 :(得分:2)

我刚刚创建了一个基本的IHttpHandler来测试这个类,它似乎可以工作。

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

我得到的结果是:

  

在.NET版本上运行测试:2.0.50727.5456

     

设置Cookie ...

     

响应:Cookie集:test = test

     

获取Cookie ...

     

响应:Cookie值:test = test

这对你来说是否正确?