Usando CookieContainer con la clase WebClient

Resuelto Maxim Zaslavsky asked hace 14 años • 5 respuestas

Anteriormente usé un CookieContainer con sesiones HttpWebRequest y HttpWebResponse, pero ahora quiero usarlo con un WebClient. Hasta donde tengo entendido, no existe un método integrado como el que existe para HttpWebRequests ( request.CookieContainer). ¿Cómo puedo recopilar cookies de un WebClient en un CookieContainer?

Busqué esto en Google y encontré el siguiente ejemplo :

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;
    }
}

¿Es esta la mejor manera de hacerlo?

Maxim Zaslavsky avatar Nov 22 '09 06:11 Maxim Zaslavsky
Aceptado
 WebClient wb = new WebClient();
 wb.Headers.Add(HttpRequestHeader.Cookie, "somecookie");

De comentarios

¿Cómo se formatea el nombre y el valor de la cookie en lugar de "alguna cookie"?

wb.Headers.Add(HttpRequestHeader.Cookie, "cookiename=cookievalue"); 

Para múltiples cookies:

wb.Headers.Add(HttpRequestHeader.Cookie, 
              "cookiename1=cookievalue1;" +
              "cookiename2=cookievalue2");
Rajeesh avatar Oct 22 '2011 18:10 Rajeesh

Sí. En mi humilde opinión, anular GetWebRequest() es la mejor solución para la funcionalidad limitada de WebClient. Antes de conocer esta opción, escribí muchos códigos realmente dolorosos en la capa HttpWebRequest porque WebClient casi, pero no del todo, hacía lo que necesitaba. La derivación es mucho más fácil.

Otra opción es utilizar la clase WebClient normal, pero completar manualmente el encabezado Cookie antes de realizar la solicitud y luego extraer el encabezado Set-Cookies en la respuesta. Hay métodos auxiliares en la clase CookieContainer que facilitan la creación y el análisis de estos encabezados: CookieContainer.SetCookies()y CookieContainer.GetCookieHeader(), respectivamente.

Prefiero el primer enfoque ya que es más fácil para la persona que llama y requiere menos código repetitivo que la segunda opción. Además, el enfoque de derivación funciona de la misma manera para múltiples escenarios de extensibilidad (por ejemplo, cookies, servidores proxy, etc.).

Justin Grant avatar Nov 22 '2009 00:11 Justin Grant

Esta es solo una extensión del artículo que encontraste.


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);
        }
    }
}
Pavel Savara avatar Jul 17 '2012 13:07 Pavel Savara

Creo que hay una forma más limpia en la que no es necesario crear un nuevo cliente web (y también funcionará con bibliotecas de terceros)

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;
        }
    }
}

Ahora todo lo que tienes que hacer es elegir qué dominios quieres usar:

    WebRequest.RegisterPrefix("http://example.com/", MyWebRequestCreator.MyHttp);

Eso significa que CUALQUIER solicitud web que vaya a example.com ahora utilizará su creador de solicitudes web personalizado, incluido el cliente web estándar. Este enfoque significa que no tienes que tocar todo tu código. Simplemente llame al prefijo de registro una vez y listo. También puede registrarse con el prefijo "http" para optar por todo en todas partes.

dotMorten avatar May 20 '2015 18:05 dotMorten