使用CookieContainer和WebClient类
我以前用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; } }
这是做这件事的最好方法吗?
是。 恕我直言,重写GetWebRequest()是WebClient的有限function的最佳解决scheme。 在我知道这个选项之前,我在HttpWebRequest层写了很多非常痛苦的代码,因为WebClient几乎但不是完成我所需要的。 派生更容易。
另一个select是使用常规WebClient类,但是在发出请求之前手动填充Cookie标题,然后在响应中提取Set-Cookies标题。 CookieContainer类中有一些帮助器方法,它们可以更容易地创build和parsing这些头文件: CookieContainer.SetCookies()
和CookieContainer.GetCookieHeader()
。
我更喜欢前面的方法,因为调用者更容易,并且比第二个选项需要更less的重复代码。 此外,派生方法对于多个可扩展性场景(例如,Cookie,代理等)的工作方式相同。
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");
这个只是你find的文章的扩展。
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); } } }
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; } }
我认为有更清晰的方法,你不需要创build一个新的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; } } }
现在你所要做的就是select你要使用的域名:
WebRequest.RegisterPrefix("http://example.com/", MyWebRequestCreator.MyHttp);
这意味着任何去example.com的webrequest现在将使用您的自定义webrequest创build者,包括标准webclient。 这种方法意味着你不必触摸你所有的代码。 您只需调用一次注册前缀并完成它。 你也可以注册“http”前缀来select所有的地方。