Domanda

Ho già usato un CookieContainer con HttpWebRequest e HttpWebResponse sessioni, ma ora, voglio usarlo con un WebClient. Per quanto ho capito, non v'è alcun metodo incorporato che ci sia per HttpWebRequests (request.CookieContainer). Come faccio a raccogliere i cookie da un WebClient in un CookieContainer?

I googled per questo e ho trovato il seguente esempio :

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

E 'questo il modo migliore per farlo?

È stato utile?

Soluzione

Sì. IMHO, sovrascrivendo GetWebRequest () è la soluzione migliore per limitata functionalty di WebClient. Prima lo sapevo su questa opzione, ho scritto un sacco di codice davvero doloroso a livello di HttpWebRequest perché WebClient quasi, ma non del tutto, ha fatto quello che mi serviva. Derivazione è molto più facile.

Un'altra opzione è quella di utilizzare la classe WebClient regolare, ma popolare manualmente l'intestazione cookie prima di effettuare la richiesta e quindi estrarre l'intestazione Set-Cookie sulla risposta. Ci sono metodi di supporto sulla classe CookieContainer che rendono la creazione e l'analisi queste intestazioni facile: CookieContainer.SetCookies() e CookieContainer.GetCookieHeader() , rispettivamente.

Io preferisco il primo approccio in quanto è più facile per il chiamante e richiede meno codice ripetitivo rispetto alla seconda opzione. Inoltre, l'approccio di derivazione funziona allo stesso modo per i molteplici scenari di estensibilità (ad esempio i cookie, proxy, ecc.).

Altri suggerimenti

 WebClient wb = new WebClient();
 wb.Headers.Add(HttpRequestHeader.Cookie, "somecookie");

Da Commenti

Come si formatta il nome e valore del cookie al posto di "somecookie"?

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

Per più cookie:

wb.Headers.Add(HttpRequestHeader.Cookie, 
              "cookiename1=cookievalue1;" +
              "cookiename2=cookievalue2");

Questo è solo l'estensione di un articolo che hai trovato.


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

Il HttpWebRequest modifica l'CookieContainer ad esso assegnato. Non c'è bisogno di elaborare i cookie restituiti. È sufficiente assegnare il contenitore di cookie per ogni richiesta 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;
    }
}

Credo che ci sia modo più pulito dove non c'è bisogno di creare un nuovo WebClient (e funzionerà con le librerie 3a parte così)

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

Ora tutto ciò che dovete fare è optare per cui domini si desidera utilizzare questo:

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

Questo significa che ogni WebRequest che va a example.com sarà ora possibile utilizzare la vostra abitudine WebRequest creatore, tra cui il WebClient standard. Questo approccio significa che non c'è bisogno di toccare tutto il codice. Basta chiamare il prefisso registro una sola volta e da fare con esso. È anche possibile registrare per il prefisso "http" di opt-in per tutto ovunque.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top