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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top