WebClientクラスでcookiecontainerを使用します
-
21-09-2019 - |
質問
私は以前、httpwebrequestとhttpwebresponseセッションを備えたCookieContainerを使用しましたが、今ではWebClientで使用したいと思います。私が理解している限り、httpwebrequestsのような組み込み方法はありません(request.CookieContainer
). CookieContainerのWebClientからCookieを収集するにはどうすればよいですか?
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;
}
}
これはそれをするための最良の方法ですか?
解決
はい。 Imho、Overriding getWebRequest()は、WebClientの限られた機能性の最良のソリューションです。このオプションを知る前に、WebClientがほとんど、しかしまったく必要なことをしたことがあるため、HTTPWEBREQUESTレイヤーに非常に痛みを伴うコードをたくさん書きました。派生ははるかに簡単です。
別のオプションは、通常のWebClientクラスを使用することですが、リクエストを行う前にCookieヘッダーを手動で入力してから、応答でセットクーキーヘッダーを引き出します。 CookieContainerクラスには、これらのヘッダーの作成と解析を簡単にするヘルパーメソッドがあります。 CookieContainer.SetCookies()
と CookieContainer.GetCookieHeader()
, 、 それぞれ。
発信者にとっては簡単で、2番目のオプションよりも繰り返しコードが少ないため、以前のアプローチを好みます。また、派生アプローチは、複数の拡張性シナリオ(Cookie、Proxiesなど)で同じように機能します。
他のヒント
WebClient wb = new WebClient();
wb.Headers.Add(HttpRequestHeader.Cookie, "somecookie");
コメントから
「SomeCookie」の代わりにCookieの名前と価値をどのようにフォーマットしますか?
wb.Headers.Add(HttpRequestHeader.Cookie, "cookiename=cookievalue");
複数のクッキーの場合:
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);
}
}
}
HTTPWEBREQUESTは、割り当てられたCookIeContainerを変更します。返されたCookieを処理する必要はありません。すべてのWebリクエストにCookieコンテナを割り当てるだけです。
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;
}
}
新しい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は、標準のWebClientを含むカスタムWebRequest Creatorを使用するようになりました。このアプローチは、コードをすべて触れる必要がないことを意味します。レジスタのプレフィックスを一度呼び出して、それで完了します。 「HTTP」プレフィックスに登録して、どこでもすべてをオプトインすることもできます。