Esforço ao tentar obter o cookie da resposta com HttpClient em .net 4.5

107

Eu tenho o seguinte código que funciona com sucesso. Não consigo descobrir como tirar o cookie da resposta. Meu objetivo é poder definir cookies na solicitação e obter cookies da resposta. Pensamentos?

private async Task<string> Login(string username, string password)
{
    try
    {
        string url = "http://app.agelessemail.com/account/login/";
        Uri address = new Uri(url);
        var postData = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("username", username),
            new KeyValuePair<string, string>("password ", password)
        };

        HttpContent content = new FormUrlEncodedContent(postData);
        var cookieJar = new CookieContainer();
        var handler = new HttpClientHandler
        {
            CookieContainer = cookieJar,
            UseCookies = true,
            UseDefaultCredentials = false
        };

        var client = new HttpClient(handler)
        {
            BaseAddress = address
        };


        HttpResponseMessage response = await client.PostAsync(url,content);
        response.EnsureSuccessStatusCode();
        string body = await response.Content.ReadAsStringAsync();
        return body;
    }
    catch (Exception e)
    {
        return e.ToString();
    }
}

Aqui está a resposta completa:

HttpResponseMessage response = await client.PostAsync(url,content);
response.EnsureSuccessStatusCode();

Uri uri = new Uri(UrlBase);
var responseCookies = cookieJar.GetCookies(uri);
foreach (Cookie cookie in responseCookies)
{
    string cookieName = cookie.Name;
    string cookieValue = cookie.Value;
}
Peter Kellner
fonte
Por curiosidade, posso perguntar por que você deseja ler cookies no cliente? Meu entendimento é que os cookies são usados ​​para enviar informações ao servidor, não para retornar informações.
Darrel Miller
Eu uso o cookie retornado em chamadas que retornam JSON para que não precise fazer uma chamada de autorização separada para cada chamada JSON. Ou seja, tenho um registro de chamadas / Home / GetData que retorna JSON, mas somente se autorizado. Na solicitação do cliente, adiciono o cookie para que / Home / GetData responda. Caso contrário, dirá "403" não autorizado.
Peter Kellner
Definir o cabeçalho de autorização como um cabeçalho padrão é quase tão eficaz e um pouco mais padrão. Simplesmente não há como o servidor definir o cabeçalho de autenticação automaticamente em nome do cliente.
Darrel Miller
1
obrigado pela dica Darrel. Você tem algum exemplo de como isso pode ser no asp.net? Lutei com isso para o meu monotouch e agora meu aplicativo da Windows Store. Eu ficaria feliz se houvesse uma maneira simples. Isso é uma dor, especialmente com async e await now nos aplicativos da Windows Store.
Peter Kellner

Respostas:

170

Para adicionar cookies a uma solicitação, preencha o contêiner de cookies antes da solicitação com CookieContainer.Add(uri, cookie). Depois que a solicitação for feita, o contêiner de cookies será preenchido automaticamente com todos os cookies da resposta. Você pode então chamar GetCookies () para recuperá-los.

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;

HttpClient client = new HttpClient(handler);
HttpResponseMessage response = client.GetAsync("http://google.com").Result;

Uri uri = new Uri("http://google.com");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
    Console.WriteLine(cookie.Name + ": " + cookie.Value);

Console.ReadLine();
Despertar
fonte
8
Nota: Após receber os cookies iniciais na primeira chamada, ao acessar quaisquer páginas do mesmo domínio, os cookies serão enviados automaticamente, sem necessidade de etapas adicionais.
Jahmic de
Você deve adicionar "using System.linq;"
Cabuxa.Mapache
^^ System.Linq só é necessário se você deseja utilizar o método .Cast <>, não é necessário para a recuperação de cookies, mas deve ser autoexplicativo :)
MikeDub
É possível obter cookies da mesma forma se httpclientfor compilado na fábrica httpclient? isto é, método do construtor adicionado a services.AddHttpClient
user3279954
no get Async, já fizemos uma referência a "google.com", por que precisamos declarar um URI com uma referência a ele novamente?
Malcolm Salvador
7

Há alternativa se você não tiver acesso HttpCliente não puder injetar o CookieContainer. Isso funciona no .NET Core 2.2:

private string GetCookie(HttpResponseMessage message)
{
    message.Headers.TryGetValues("Set-Cookie", out var setCookie);
    var setCookieString = setCookie.Single();
    var cookieTokens = setCookieString.Split(';');
    var firstCookie = cookieTokens.FirstOrDefault();
    var keyValueTokens = firstCookie.Split('=');
    var valueString = keyValueTokens[1];
    var cookieValue = HttpUtility.UrlDecode(valueString);
    return cookieValue;
}
Rytis I
fonte
1
Brilhante e cru, mas exatamente o que eu preciso ... Bom trabalho, obrigado.
Vedran Mandić
5

Você pode obter facilmente um valor de cookie com o URL fornecido.

private async Task<string> GetCookieValue(string url, string cookieName)
{
    var cookieContainer = new CookieContainer();
    var uri = new Uri(url);
    using (var httpClientHandler = new HttpClientHandler
    {
        CookieContainer = cookieContainer
    })
    {
        using (var httpClient = new HttpClient(httpClientHandler))
        {
            await httpClient.GetAsync(uri);
            var cookie = cookieContainer.GetCookies(uri).Cast<Cookie>().FirstOrDefault(x => x.Name == cookieName);
            return cookie?.Value;
        }
    }
}
Alper Ebicoglu
fonte