将CookieContainer与WebClient类一起使用

Max*_*sky 142 c# cookies webclient httpwebrequest cookiecontainer

我之前使用过带有HttpWebRequest和HttpWebResponse会话的CookieContainer,但现在,我想将它与WebClient一起使用.据我所知,没有像HttpWebRequests(request.CookieContainer)那样的内置方法.如何从CookieContainer中的WebClient收集cookie?

我用Google搜索并找到以下示例:

public class CookieAwareWebClient : WebClient
{
    private readonly CookieContainer m_container = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        HttpWebRequest webRequest = request as HttpWebRequest;
        if (webRequest != null)
        {
            webRequest.CookieContainer = m_container;
        }
        return request;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是最好的方法吗?

小智 113

 WebClient wb = new WebClient();
 wb.Headers.Add(HttpRequestHeader.Cookie, "somecookie");
Run Code Online (Sandbox Code Playgroud)

来自评论

你如何格式化cookie的名称和价值来代替"somecookie"?

wb.Headers.Add(HttpRequestHeader.Cookie, "cookiename=cookievalue"); 
Run Code Online (Sandbox Code Playgroud)

对于多个cookie:

wb.Headers.Add(HttpRequestHeader.Cookie, 
              "cookiename1=cookievalue1;" +
              "cookiename2=cookievalue2");
Run Code Online (Sandbox Code Playgroud)

  • @Neil N:wb.Headers.Add(HttpRequestHeader.Cookie,"cookiename = cookievalue"); 对于多个cookie:wb.Headers.Add(HttpRequestHeader.Cookie,"cookiename1 = cookievalue1; cookiename2 = cookievalue2"); (10认同)

Jus*_*ant 69

是.恕我直言,重写GetWebRequest()是WebClient功能有限的最佳解决方案.在我知道这个选项之前,我在HttpWebRequest层编写了许多非常痛苦的代码,因为WebClient几乎(但并不完全)完成了我需要的工作.推导更容易.

另一种选择是使用常规WebClient类,但在发出请求之前手动填充Cookie标头,然后在响应上拉出Set-Cookies标头.CookieContainer类上有一些帮助方法,可以更轻松地创建和解析这些标题:CookieContainer.SetCookies()CookieContainer.GetCookieHeader().

我更喜欢前一种方法,因为它对调用者来说更容易,并且需要的重复代码少于第二种选择.此外,派生方法对于多个可扩展性场景(例如cookie,代理等)的工作方式相同.


Pav*_*ara 46

这个只是您找到的文章的扩展.


public class WebClientEx : WebClient
{
    public WebClientEx(CookieContainer container)
    {
        this.container = container;
    }

    public CookieContainer CookieContainer
        {
            get { return container; }
            set { container= value; }
        }

    private CookieContainer container = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest r = base.GetWebRequest(address);
        var request = r as HttpWebRequest;
        if (request != null)
        {
            request.CookieContainer = container;
        }
        return r;
    }

    protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
    {
        WebResponse response = base.GetWebResponse(request, result);
        ReadCookies(response);
        return response;
    }

    protected override WebResponse GetWebResponse(WebRequest request)
    {
        WebResponse response = base.GetWebResponse(request);
        ReadCookies(response);
        return response;
    }

    private void ReadCookies(WebResponse r)
    {
        var response = r as HttpWebResponse;
        if (response != null)
        {
            CookieCollection cookies = response.Cookies;
            container.Add(cookies);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然你可以通过展示如何使用类的功能来改进这个答案,尤其是设置和获取cookie,但这样做效果很好.@ Pavel. (3认同)
  • 实际上,您不需要GetWebResponse和ReadCookies,因为cookie会自动添加到容器中。 (2认同)

小智 11

HttpWebRequest修改分配给它的CookieContainer.无需处理返回的cookie.只需将cookie容器分配给每个Web请求.

public class CookieAwareWebClient : WebClient
{
    public CookieContainer CookieContainer { get; set; } = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri uri)
    {
        WebRequest request = base.GetWebRequest(uri);
        if (request is HttpWebRequest)
        {
            (request as HttpWebRequest).CookieContainer = CookieContainer;
        }
        return request;
    }
}
Run Code Online (Sandbox Code Playgroud)


dot*_*ten 6

我认为有一种更清洁的方式,你不必创建一个新的webclient(它也适用于第三方库)

internal static class MyWebRequestCreator
{
    private static IWebRequestCreate myCreator;

    public static IWebRequestCreate MyHttp
    {
        get
        {
            if (myCreator == null)
            {
                myCreator = new MyHttpRequestCreator();
            }
            return myCreator;
        }
    }

    private class MyHttpRequestCreator : IWebRequestCreate
    {
        public WebRequest Create(Uri uri)
        {
            var req = System.Net.WebRequest.CreateHttp(uri);
            req.CookieContainer = new CookieContainer();
            return req;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您只需选择要使用的域名:

    WebRequest.RegisterPrefix("http://example.com/", MyWebRequestCreator.MyHttp);
Run Code Online (Sandbox Code Playgroud)

这意味着发送到example.com的任何webrequest现在都将使用您的自定义webrequest创建者,包括标准webclient.这种方法意味着您不必触摸所有代码.您只需调用一次寄存器前缀即可完成.您还可以注册"http"前缀以选择所有地方的所有内容.