CookieContainer'ı WebClient sınıfıyla kullanma


148

Daha önce HttpWebRequest ve HttpWebResponse oturumlarıyla bir CookieContainer kullandım, ancak şimdi bir WebClient ile kullanmak istiyorum. Anladığım kadarıyla, HttpWebRequests ( request.CookieContainer) gibi yerleşik bir yöntem yoktur . Bir CookieContainer'da bir WebClient'ten nasıl çerez toplayabilirim?

Bunun için googled ve aşağıdaki örnek bulundu :

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

Bunu yapmanın en iyi yolu bu mu?


1
Benim açımdan m_containerasla ayarlanmadı !? Her zaman boş değil mi?
C4d

HttpWebRequest sınıfının m_container sınıfını iç alanını CookieContainer'ı gerektiği gibi kullanarak değiştirdiğine inanıyorum.
HeartWare

Tek ihtiyacınız olan bu! Yanıtlardaki çerezler kapsayıcıya otomatik olarak eklenecektir.
lionello

Yanıtlar:


69

Evet. IMHO, GetWebRequest () 'i geçersiz kılmak WebClient'in sınırlı işlevselliği için en iyi çözümdür. Bu seçeneği bilmeden önce, HttpWebRequest katmanına gerçekten acı veren bir sürü kod yazdım çünkü WebClient neredeyse ihtiyacım olanı yaptı. Derivasyon çok daha kolaydır.

Başka bir seçenek, normal WebClient sınıfını kullanmaktır, ancak istek yapmadan önce Çerez başlığını el ile doldurmak ve ardından yanıttaki Set-Cookies başlığını dışarı çıkarmaktır. CookieContainer sınıfında bu başlıkları oluşturmayı ve ayrıştırmayı kolaylaştıran yardımcı yöntemler vardır: CookieContainer.SetCookies()ve CookieContainer.GetCookieHeader()sırasıyla.

Arayan için daha kolay olduğu ve ikinci seçeneğe göre daha az tekrarlayan kod gerektirdiği için eski yaklaşımı tercih ediyorum. Ayrıca, türetme yaklaşımı, birden çok genişletilebilirlik senaryosu (çerezler, proxy'ler, vb.) İçin aynı şekilde çalışır.


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

Yorumlardan

Çerezin adını ve değerini "kurabiye" yerine nasıl biçimlendirirsiniz?

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

Birden çok çerez için:

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

Çerezin adını ve değerini "kurabiye" yerine nasıl biçimlendirirsiniz?
Neil N

11
@Neil N: wb.Headers.Add (HttpRequestHeader.Cookie, "cookiename = cookievalue"); Birden çok çerez için: wb.Headers.Add (HttpRequestHeader.Cookie, "cookiename1 = cookievalue1; cookiename2 = cookievalue2");
Ian Kemp

46

Bu sadece bulduğunuz makalenin uzantısıdır.


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

3
Bu, @Pavel'de iyi çalıştı, ancak sınıfın özelliklerini nasıl kullanacağınızı, özellikle de çerezleri ayarlayıp alarak bu cevabı geliştirebilirsiniz.
Ağustos'ta Corgalore

Uzatma için teşekkürler. Bunu kullanmak için genel CookieContainer CookieContainer {get {return _container; } set {_container = değer; }}
Igor Shubin

1
@IgorShubin alanın readonlydeğiştiricisini kaldırmanız gerekir container, aksi takdirde onu mülkte ayarlayamazsınız. Kodu değiştirdim.
Aralık'ta

1
Set-CookieYanıt başlığını kontrol etmemeniz gerekir ReadCookiesmi?
Aşil

2
Aslında gerek yok GetWebResponseve ReadCookiesçerezleri otomatik olarak kaba ilave alacak beri.
lionello

15

HttpWebRequest kendisine atanan CookieContainer'ı değiştirir. İade edilen çerezleri işlemeye gerek yoktur. Çerez kabınızı her web isteğine atamanız yeterlidir.

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

6

Yeni bir web istemcisi oluşturmak zorunda olmadığınız daha temiz bir yol olduğunu düşünüyorum (ve 3. taraf kütüphanelerle de çalışacak)

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

Şimdi tek yapmanız gereken, hangi alanları kullanmak istediğinizi seçmek:

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

Bu, example.com'a giden HERHANGİ BİR web isteğinin artık standart web istemcisi de dahil olmak üzere özel web isteği oluşturucunuzu kullanacağı anlamına gelir. Bu yaklaşım, tüm kodlarınıza dokunmanız gerekmediği anlamına gelir. Sadece kayıt önekini bir kez çağırırsınız ve onunla işiniz biter. Her yerde her şeyi seçmek için "http" önekine de kaydolabilirsiniz.


Son birkaç cümleden emin değilim; dokümanlar ki: "HttpWebRequest sınıfı varsayılan olarak HTTP ve HTTPS düzenlemeler yapan isteklerine kayıtlı girişimleri başarısız olur bu düzenleri için farklı bir WebRequest torunu kayıt.."
Herohtar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.