我之前使用过带有HttpWebRequest和HttpWebResponse会话的CookieContainer,但是现在,我想将它与WebClient一起使用。据我所知,没有像HttpWebRequests(request.CookieContainer
)那样的内置方法。 如何从CookieContainer中的WebClient收集Cookie?
我googled为此而找到the following sample:
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;
}
}
这是最好的方法吗?
答案 0 :(得分:105)
WebClient wb = new WebClient();
wb.Headers.Add(HttpRequestHeader.Cookie, "somecookie");
来自评论
如何格式化cookie的名称和价值来代替“somecookie”?
wb.Headers.Add(HttpRequestHeader.Cookie, "cookiename=cookievalue");
对于多个Cookie:
wb.Headers.Add(HttpRequestHeader.Cookie,
"cookiename1=cookievalue1;" +
"cookiename2=cookievalue2");
答案 1 :(得分:68)
是。恕我直言,重写GetWebRequest()是WebClient功能有限的最佳解决方案。在我知道这个选项之前,我在HttpWebRequest层编写了许多非常痛苦的代码,因为WebClient几乎(但并不完全)完成了我需要的工作。推导更容易。
另一种选择是使用常规WebClient类,但在发出请求之前手动填充Cookie标头,然后在响应上拉出Set-Cookies标头。 CookieContainer类上有辅助方法,可以更轻松地创建和解析这些标题:CookieContainer.SetCookies()
和CookieContainer.GetCookieHeader()
。
我更喜欢前一种方法,因为它对调用者来说更容易,并且需要的重复代码少于第二种选择。此外,派生方法对于多个可扩展性方案(例如cookie,代理等)的工作方式相同。
答案 2 :(得分:45)
这只是您找到的文章的扩展名。
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);
}
}
}
答案 3 :(得分: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;
}
}
答案 4 :(得分: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;
}
}
}
现在,您只需选择要使用的域名:
WebRequest.RegisterPrefix("http://example.com/", MyWebRequestCreator.MyHttp);
这意味着转到example.com的任何webrequest现在都将使用您的自定义webrequest创建者,包括标准webclient。这种方法意味着您不必触摸所有代码。您只需调用一次寄存器前缀即可完成。 您还可以注册“http”前缀以选择任何地方的所有内容。