Usando CookieContainer com aula WebClient
-
21-09-2019 - |
Pergunta
Eu já usei um cookieContainer com sessões HTTPWebRequest e HttpwebroSponse, mas agora quero usá -lo com um webclient. Até onde eu entendo, não há método interno como existe para httpwebrequests (request.CookieContainer
). Como posso coletar cookies de um webclient em um cookieContainer?
EU Google para isso e encontrado a amostra a seguir:
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;
}
}
Esse é o melhor jeito de fazer isso?
Solução
Sim. IMHO, Substituindo getWebRequest () é a melhor solução para a funcionalidade limitada do WebClient. Antes de saber sobre essa opção, escrevi muito código realmente doloroso na camada httpwebrequest porque quase, mas não exatamente, fazia o que eu precisava. A derivação é muito mais fácil.
Outra opção é usar a classe WebClient regular, mas preencher manualmente o cabeçalho do biscoito antes de fazer a solicitação e retirar o cabeçalho dos cozinheiros da resposta. Existem métodos auxiliares na classe CookieContainer que facilitam a criação e a análise desses cabeçalhos: CookieContainer.SetCookies()
e CookieContainer.GetCookieHeader()
, respectivamente.
Prefiro a abordagem anterior, pois é mais fácil para o chamador e requer um código menos repetitivo do que a segunda opção. Além disso, a abordagem de derivação funciona da mesma maneira para vários cenários de extensibilidade (por exemplo, cookies, proxies, etc.).
Outras dicas
WebClient wb = new WebClient();
wb.Headers.Add(HttpRequestHeader.Cookie, "somecookie");
De comentários
Como você formate o nome e o valor do cookie no lugar de "SomeeCookie"?
wb.Headers.Add(HttpRequestHeader.Cookie, "cookiename=cookievalue");
Para vários cookies:
wb.Headers.Add(HttpRequestHeader.Cookie,
"cookiename1=cookievalue1;" +
"cookiename2=cookievalue2");
Este é apenas uma extensão do artigo que você encontrou.
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);
}
}
}
O httpwebrequest modifica o cookieContainer atribuído a ele. Não há necessidade de processar cookies retornados. Basta atribuir seu contêiner de cookie a todas as solicitações da 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;
}
}
Eu acho que há uma maneira mais limpa em que você não precisa criar um novo webclient (e funcionará com bibliotecas de terceiros também)
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;
}
}
}
Agora tudo o que você precisa fazer é optar por quais domínios você deseja usar isso:
WebRequest.RegisterPrefix("http://example.com/", MyWebRequestCreator.MyHttp);
Isso significa que qualquer WebRequest que vai para Exement.com agora usará o seu criador WebRequest personalizado, incluindo o WebClient padrão. Essa abordagem significa que você não precisa tocar todo o código. Você acabou de ligar para o prefixo do registro uma vez e terminar com ele. Você também pode se inscrever no prefixo "http" para optar por tudo em todos os lugares.