Вопрос

Ранее я использовал CookieContainer с сеансами httpwebrequest и httpwebresponse, но теперь я хочу использовать его с веб -клиентом. Насколько я понимаю, нет встроенного метода, как для httpwebrequests (request.CookieContainer). Как я могу собирать cookie из веб -клиента в кулинарном виде?

я гуглил Для этого и нашел Следующий образец:

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

Это лучший способ сделать это?

Это было полезно?

Решение

Да. IMHO, переопределение getWebRequest () является лучшим решением для ограниченной функциональности WebClient. Прежде чем я узнал об этом варианте, я написал много действительно болезненного кода на слое httpwebrequest, потому что WebClient почти, но не совсем, делал то, что мне нужно. Вывод намного проще.

Другой вариант-использовать обычный класс WebClient, но вручную заполняет заголовок cookie, прежде чем сделать запрос, а затем вытащить заголовок Set-Cookies в ответе. Есть вспомогательные методы на классе CookieContainer, которые облегчают создание и анализ этих заголовков: CookieContainer.SetCookies() а также CookieContainer.GetCookieHeader(), соответственно.

Я предпочитаю первый подход, так как для вызывающего абонента легче и требует меньшего повторяющегося кода, чем второй вариант. Кроме того, подход к деривации работает одинаково для множественных сценариев расширяемости (например, файлов cookie, прокси и т. Д.).

Другие советы

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

Из комментариев

Как форматировать название и ценность печенья вместо «что -то»?

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

Для нескольких файлов cookie:

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

Это просто расширение статьи, которую вы нашли.


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

HttpWebRequest модифицирует назначенный ему cookieContainer. Нет необходимости обрабатывать возвращенные файлы cookie. Просто назначьте свой контейнер cookie по каждому веб -запросу.

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

Я думаю, что есть более чистый способ, где вам не нужно создавать новый WebClient (и он также будет работать с сторонними библиотеками)

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

Теперь все, что вам нужно сделать, это выбрать, для каких доменов вы хотите это использовать:

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

Это означает, что любой WebRequest, который идет на example.com, теперь будет использовать ваш пользовательский создатель WebRequest, включая стандартный WebClient. Этот подход означает, что вам не нужно прикасаться к коду. Вы просто вызовите префикс регистра один раз и покончить с ним. Вы также можете зарегистрироваться для префикса «HTTP», чтобы выбрать все повсюду.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top