【问题标题】:WebClient CookieContainer works well in .NET 4.0+ but not in earlier versionsWebClient CookieContainer 在 .NET 4.0+ 中运行良好,但在早期版本中不行
【发布时间】:2012-08-19 20:33:31
【问题描述】:

我正在开发一个使用 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+ 则说有应该是两个 cookie。

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

【问题讨论】:

  • 您的问题的答案可以在这里找到 - stackoverflow.com/questions/1777221/…
  • 任何人都会提供帮助,或者我必须使用更简单的解决方案而不扩展 WebClient?
  • 我的测试表明这个类按预期工作。也许您可以多解释一下为什么您认为它不起作用。

标签: c# .net webclient


【解决方案1】:

我已确认 .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);
    }
}

所以,HttpWebRequestWebClient 使用)似乎有问题。这可能是新的,因为我看到人们在 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

如果不是那么紧急,那么您可以将问题记录在 http://connect.microsoft.com/VisualStudio 以查看您是否收到有关解决方法的回复。

【讨论】:

  • 也许我会尝试其他更简单的解决方案(太糟糕了,我应该因为错误而使用糟糕的解决方案)。如果我有空闲时间,我会发布一个错误,但我认为他们知道这一点。没有人会回答 IMO,所以我会给你 +50...
【解决方案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

这对您来说是否正确?

【讨论】:

  • 我现在要测试一下。可能问题出在我的项目设置上。
  • 您的代码对我没有任何帮助,因为它是 ASP.NET 代码,而我只有 C# for Windows。我尝试再次制作项目并将代码导入其中,但结果都一样。
  • @Uhehesh - 我使用 ASP.NET 的原因是因为我能够用少量代码实现 (a) 客户端和 (b) 服务器。如果您有兴趣,我可以指导您完成如何在您的机器上进行设置。但是我想知道您是否可以提供更多详细信息,说明您所做的哪些测试/调试使您认为此类不起作用。
  • 好的,我明白了。但正如我所说,我添加了一些调试代码,它说在 1.0-3.5 中 GetWebRequest 上有 0 个 cookie,而在 4.0 和 4.5 中它说有 2 个 cookie(应该如此)。
  • 如果您无法提供有关如何测试代码的更多详细信息(可能是您如何使用它的示例),很遗憾,我无法提供更多帮助。对不起。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多