Lottando cercando di ottenere cookie dalla risposta con HttpClient in .net 4.5


107

Ho il seguente codice che funziona correttamente. Non riesco a capire come ottenere il cookie dalla risposta. Il mio obiettivo è quello di poter impostare i cookie nella richiesta e ottenere i cookie dalla risposta. Pensieri?

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

Ecco la risposta 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;
}

Per curiosità posso chiederti perché vuoi leggere i cookie sul client? A quanto mi risulta, i cookie vengono utilizzati per inviare informazioni al server, non per restituire informazioni.
Darrel Miller

Utilizzo il cookie restituito sulle chiamate che restituiscono JSON in modo da non dover eseguire una chiamata di autorizzazione separata per ogni chiamata JSON. Vale a dire, ho un registro delle chiamate / Home / GetData che restituisce JSON ma solo se autorizzato. Alla richiesta del cliente, aggiungo il cookie in modo che / Home / GetData risponda. Altrimenti dirà "403" non autorizzato.
Peter Kellner

L'impostazione dell'intestazione di autorizzazione come intestazione predefinita è quasi altrettanto efficace e un po 'più standard. Non esiste alcun modo per il server di impostare automaticamente l'intestazione di autenticazione per conto del client.
Darrel Miller

1
grazie per la punta Darrel. Hai qualche esempio di come potrebbe apparire in asp.net? Ho lottato con questo per il mio monotouch e ora la mia app di Windows Store. Sarei felice se ci fosse un modo semplice. Questo è un problema, soprattutto con async e attendo ora sulle app di Windows Store.
Peter Kellner

Risposte:


170

Per aggiungere cookie a una richiesta, popolare il contenitore dei cookie prima della richiesta con CookieContainer.Add(uri, cookie). Dopo la richiesta, il contenitore dei cookie verrà automaticamente popolato con tutti i cookie della risposta. È quindi possibile chiamare GetCookies () per recuperarli.

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

8
Nota: dopo aver ricevuto i cookie iniziali nella prima chiamata, quando si accede a qualsiasi pagina dello stesso dominio, i cookie verranno inviati automaticamente, non sono necessari passaggi aggiuntivi.
Jahmic

È necessario aggiungere "using System.linq;"
Cabuxa.Mapache

^^ System.Linq è richiesto solo se desideri utilizzare il metodo .Cast <>, non è richiesto per il recupero dei cookie, ma dovrebbe essere autoesplicativo :)
MikeDub

È possibile ottenere i cookie allo stesso modo se httpclientviene creato dalla fabbrica httpclient? ie metodo builder aggiunto a services.AddHttpClient
user3279954

su get Async abbiamo già fatto riferimento a "google.com", perché dobbiamo dichiarare nuovamente un URI con un riferimento ad esso?
Malcolm Salvador

7

C'è un'alternativa se non hai accesso a HttpCliente non puoi iniettare il file CookieContainer. Funziona in .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;
}

1
Brillante e crudo ma proprio quello che mi serve ... Bel lavoro, grazie.
Vedran Mandić

5

Puoi facilmente ottenere un valore di cookie con l'URL fornito.

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;
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.