【问题标题】:How to add cookies to WebRequest?如何将 cookie 添加到 WebRequest?
【发布时间】:2012-06-25 05:30:10
【问题描述】:

我正在尝试对一些代码进行单元测试,我需要替换它:

  HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create( uri );
  httpWebRequest.CookieContainer = new CookieContainer();

  WebRequest webRequest = WebRequest.Create( uri );
  webRequest.CookieContainer = new CookieContainer(); 

基本上,如何在不使用 HttpWebRequest 的情况下将 cookie 放入请求中?

【问题讨论】:

  • 这很难,因为 cookie 是一个 HTTP 概念。您是否有理由需要进行此更改?
  • @dlev - WebRequest 将基于 uri 创建一个 HttpWebRequest。因此,如果我想模拟我自己的 WebRequest 对象和/或注册我自己的也返回 WebRequest 的 uri,那么我不想将方法限制为仅使用 HttpWebRequest 对象。
  • 我知道webRequest 的运行时类型将是HttpWebRequest。但是访问CookieContainer 需要编译时类型为HttpWebRequest。另外,您提到不要将自己限制在 HTTP 上,但在这种情况下,cookie 并没有多大意义,因为它们是一种 HTTP 构造(这就是它们首先出现在 WebRequest 上的原因。)
  • dlev - 这就是为什么我正在寻找一种添加 cookie 的运行时方式。想象一下,如果我说 if ... 然后 addcookies ^^
  • 看这个页面。 stackoverflow.com/questions/18667931/… 这对我很有帮助

标签: c# .net unit-testing


【解决方案1】:

试试这样的:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/default.html");
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(new Cookie("ConstoCookie", "Chocolate Flavour"));

【讨论】:

  • 问题不在于将 cookie 设置为响应。这是关于创建新的 WebRequest 并为此请求设置一个 cookie(并查看问题的标签,执行来自单元测试的请求)。
  • 这将引发错误Object reference not set to an...。首先我们可能需要request.CookieContainer = new CookieContainer(); 然后调用 Add 方法应该可以工作。
【解决方案2】:

根据你的 cmets,你可以考虑写一个extension method

public static bool TryAddCookie(this WebRequest webRequest, Cookie cookie)
{
    HttpWebRequest httpRequest = webRequest as HttpWebRequest;
    if (httpRequest == null)
    {
        return false;
    }

    if (httpRequest.CookieContainer == null)
    {
        httpRequest.CookieContainer = new CookieContainer();
    }

    httpRequest.CookieContainer.Add(cookie);
    return true;
}

然后你可以有这样的代码:

WebRequest webRequest = WebRequest.Create( uri );
webRequest.TryAddCookie(new Cookie("someName","someValue"));

【讨论】:

  • 此代码返回:“参数‘{0}’不能为空字符串。”在线 httpRequest.CookieContainer.Add(cookie);。有什么想法吗?
  • @drdigit 那是因为您没有创建包含域的 cookie。另外,我很确定错误字符串是 BCL 中的一个错误(不幸的是,它似乎一直存在于 4.5 中)
  • 非常感谢您的详细回复。
  • @drdigit 没问题。感谢(可能是无意的)错误报告!
  • 我遇到了同样的问题“参数 '{0}' 不能是空字符串。”正如 dlev 所说,这是因为没有包含域。但是,我在开发过程中在本地主机上运行所有内容 (localhost:50665)。因此,对于名为“cookie”的 Cookie 对象,我添加了一个域“localhost”并修复了它。正确的语句为 cookie.Domain="localhost"。请注意,我之前尝试过 cookie.Domain="localhost:50665" 但没有用,我也尝试过 cookie.Domain="localhost:50665" 也没有用。您只需要使用“本地主机”。希望这对下一个人有所帮助。
【解决方案3】:

WebRequest 是一个没有 CookieContainer 属性的抽象类。此外,您不能使用 Headers 集合(未实现的异常),因此任何类似 webRequest.Headers.Add("Cookie", "...") 的尝试都会失败。

抱歉,您没有机会在 WebRequest 中使用 cookie。

坚持使用 HttpWebRequest 并使用其 Headers 集合添加/编辑任意数量的 cookie!

【讨论】:

  • 我没有这样做 :) HttpWebRequest.Headers.Add("Cookie", "...") 可以满足您的“if then addcookies”要求。
【解决方案4】:

dlev 的回答最终奏效了,但我在实现解决方案时遇到了问题(“参数 '{0}' 不能是空字符串。”),所以我决定编写完整的代码以防其他人遇到类似问题。

我的目标是将 html 作为字符串获取,但我需要将 cookie 添加到 Web 请求中。这是使用 cookie 下载字符串的函数:

public static string DownloadString(string url, Encoding encoding, IDictionary<string, string> cookieNameValues)
{
    using (var webClient = new WebClient())
    {
        var uri = new Uri(url);
        var webRequest = WebRequest.Create(uri);
        foreach(var nameValue in cookieNameValues)
        {
            webRequest.TryAddCookie(new Cookie(nameValue.Key, nameValue.Value, "/", uri.Host));
        }                
        var response = webRequest.GetResponse();
        var receiveStream = response.GetResponseStream();
        var readStream = new StreamReader(receiveStream, encoding);
        var htmlCode = readStream.ReadToEnd();                
        return htmlCode;
    }
}   

我们正在使用 dlev 答案中的代码:

public static bool TryAddCookie(this WebRequest webRequest, Cookie cookie)
{
    HttpWebRequest httpRequest = webRequest as HttpWebRequest;
    if (httpRequest == null)
    {
        return false;
    }

    if (httpRequest.CookieContainer == null)
    {
        httpRequest.CookieContainer = new CookieContainer();
    }

    httpRequest.CookieContainer.Add(cookie);
    return true;
}

这是您使用完整代码的方式:

var cookieNameValues = new Dictionary<string, string>();
cookieNameValues.Add("varName", "varValue");
var htmlResult = DownloadString(url, Encoding.UTF8, cookieNameValues);

【讨论】:

    猜你喜欢
    • 2018-06-20
    • 2022-10-23
    • 2016-11-23
    • 2021-09-12
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    相关资源
    最近更新 更多