C# 将CookieContainer与WebClient类一起使用

C# 将CookieContainer与WebClient类一起使用,c#,cookies,httpwebrequest,webclient,cookiecontainer,C#,Cookies,Httpwebrequest,Webclient,Cookiecontainer,我以前在HttpWebRequest和HttpWebResponse会话中使用过CookieContainer,但现在,我想在WebClient中使用它。据我所知,没有像HttpWebRequests(request.CookieContainer)那样的内置方法如何从CookieContainer中的网络客户端收集cookie? 我对此进行了调查,并发现: 这是最好的方法吗?是的。总之,重写GetWebRequest()是解决WebClient有限功能的最佳解决方案。在我了解这个选项之前,我在

我以前在HttpWebRequest和HttpWebResponse会话中使用过CookieContainer,但现在,我想在WebClient中使用它。据我所知,没有像HttpWebRequests(
request.CookieContainer
)那样的内置方法如何从CookieContainer中的网络客户端收集cookie?

我对此进行了调查,并发现:


这是最好的方法吗?

是的。总之,重写GetWebRequest()是解决WebClient有限功能的最佳解决方案。在我了解这个选项之前,我在HttpWebRequest层编写了很多非常痛苦的代码,因为WebClient几乎完成了我所需要的,但不是完全完成了。推导要容易得多

另一个选项是使用常规WebClient类,但在发出请求之前手动填充Cookie头,然后在响应上拉出Set Cookie头。CookieContainer类上有一些帮助器方法,它们使创建和解析这些头文件变得更容易:分别是和

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

来自评论


如何设置cookie的名称和值的格式以代替“somecookie”

对于多个cookie:

wb.Headers.Add(HttpRequestHeader.Cookie, 
              "cookiename1=cookievalue1;" +
              "cookiename2=cookievalue2");

这只是你找到的文章的延伸


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

我认为有一种更干净的方法,您不必创建新的webclient(它也可以与第三方库一起使用)

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

    WebRequest.RegisterPrefix("http://example.com/", MyWebRequestCreator.MyHttp);
这意味着进入example.com的任何webrequest现在都将使用您的自定义webrequest创建者,包括标准webclient。这种方法意味着您不必接触所有代码。只需调用寄存器前缀一次,即可完成操作。
您还可以注册“http”前缀以选择所有内容。

HttpWebRequest修改分配给它的CookieContainer。不需要处理返回的cookies。只需将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;
    }
}

如何设置cookie的名称和值的格式以代替“somecookie”?@Neil N:wb.Headers.Add(HttpRequestHeader.cookie,“cookiename=cookievalue”);对于多个Cookie:wb.Headers.Add(HttpRequestHeader.Cookie,“cookiename1=cookievalue1;cookiename2=cookievalue2”);这对我来说是最简单的方法,将cookie从Anglesharp传输到WebClient,以获得下载链接:-)谢谢!这在@Pavel中运行得很好,不过您可以通过展示如何使用类的功能来改进这个答案,特别是设置和获取cookies。Thx用于扩展。为了使用它,我添加了公共CookieContainer CookieContainer{get{return{U container;}set{U container=value;}}@IgorShubin您必须删除
container
字段的
只读
修饰符,否则无法在属性中设置它。我修改了代码。你不应该检查
ReadCookies
中的
Set Cookie
响应头吗?你实际上不需要
GetWebResponse
ReadCookies
,因为cookies会自动添加到容器中。在我看来,
m_container
从未设置过!?它不是总是空的吗?我相信HttpWebRequest类会根据需要使用其内部字段CookieContainer来修改m_容器类。这就是您所需要的!来自回复的cookies将自动添加到容器中;声明:“默认情况下,HttpWebRequest类注册为HTTP和HTTPS方案的服务请求。尝试为这些方案注册其他WebRequest子代将失败。”

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);
        }
    }
}
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;
        }
    }
}
    WebRequest.RegisterPrefix("http://example.com/", MyWebRequestCreator.MyHttp);
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;
    }
}