Używanie CookieContainer z klasą WebClient

Wcześniej używałem CookieContainer z sesjami HttpWebRequest i HttpWebResponse, ale teraz chcę go używać z WebClient. O ile dobrze rozumiem, nie ma wbudowanej metody jak dla HttpWebRequests (request.CookieContainer). Jak mogę zbierać pliki cookie z WebClient w CookieContainer?

I wyszukałem dla tego i znalazłem następującą próbkę :

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;
    }
}
Czy to najlepszy sposób?
Author: Nathan Baulch, 2009-11-21

5 answers

Tak. IMHO, nadrzędne GetWebRequest() jest najlepszym rozwiązaniem dla ograniczonej funkcji WebClient. Zanim dowiedziałem się o tej opcji, napisałem wiele naprawdę bolesnego kodu na warstwie HttpWebRequest, ponieważ WebClient prawie, ale nie do końca, zrobił to, czego potrzebowałem. Wyprowadzenie jest znacznie łatwiejsze.

Inną opcją jest użycie zwykłej klasy WebClient, ale ręczne wypełnienie nagłówka pliku Cookie przed wysłaniem żądania, a następnie wyciągnięcie nagłówka Set-Cookies w odpowiedzi. Są pomocnicy metody na klasie CookieContainer, które ułatwiają tworzenie i parsowanie tych nagłówków: CookieContainer.SetCookies() oraz CookieContainer.GetCookieHeader(), odpowiednio.

Wolę pierwsze podejście, ponieważ jest łatwiejsze dla rozmówcy i wymaga mniej powtarzalnego kodu niż druga opcja. Ponadto podejście derywacyjne działa w ten sam sposób w przypadku wielu scenariuszy rozszerzalności (np. plików cookie, serwerów proxy itp.).

 69
Author: Justin Grant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-22 00:52:07
 WebClient wb = new WebClient();
 wb.Headers.Add(HttpRequestHeader.Cookie, "somecookie");

From Comments

Jak sformatować nazwę i wartość pliku cookie zamiast "somecookie"?

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

Dla wielu plików cookie:

wb.Headers.Add(HttpRequestHeader.Cookie, 
              "cookiename1=cookievalue1;" +
              "cookiename2=cookievalue2");
 120
Author: Rajeesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-07 23:03:51

Ten jest tylko rozszerzeniem artykułu, który znalazłeś.


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);
        }
    }
}
 46
Author: Pavel Savara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-08 13:24:12

HttpWebRequest modyfikuje przypisany do niego plik CookieContainer. Nie ma potrzeby przetwarzania zwracanych plików cookie. Wystarczy przypisać kontener cookie do każdego żądania internetowego.

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;
    }
}
 15
Author: Ted,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-12 23:00:17

Myślę, że jest czystszy sposób, w którym nie trzeba tworzyć nowego webclient (i będzie działać również z bibliotekami innych firm)

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

Teraz wystarczy wybrać domeny, z których chcesz skorzystać:

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

Czyli każdy webrequest, który trafia do example.com będzie teraz używać niestandardowego kreatora webrequest, w tym standardowego webclient. Takie podejście oznacza, że nie musisz dotykać całego kodu. Wystarczy, że raz zadzwonisz do prefiksu rejestru i skończysz z tym. Możesz Zarejestruj się również na prefiks "http", aby zdecydować się na wszystko wszędzie.

 6
Author: dotMorten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-20 18:58:02