Difficulté à essayer d'obtenir le cookie de la réponse avec HttpClient dans .net 4.5

107

J'ai le code suivant qui fonctionne avec succès. Je ne peux pas comprendre comment retirer le cookie de la réponse. Mon objectif est que je souhaite pouvoir définir des cookies dans la demande et supprimer les cookies de la réponse. Pensées?

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

Voici la réponse complète:

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
la source
Par curiosité, puis-je vous demander pourquoi vous souhaitez lire des cookies sur le client? Je crois comprendre que les cookies sont utilisés pour envoyer des informations au serveur, pas pour renvoyer des informations.
Darrel Miller
J'utilise le cookie renvoyé sur les appels qui renvoient JSON afin de ne pas avoir à faire un appel d'autorisation distinct pour chaque appel JSON. C'est-à-dire que j'ai un journal des appels / Home / GetData qui renvoie JSON mais uniquement s'il est autorisé. À la demande du client, j'ajoute le cookie pour que / Home / GetData réponde. Sinon, il dira "403" non autorisé.
Peter Kellner
La définition de l'en-tête d'autorisation comme en-tête par défaut est presque aussi efficace et un peu plus standard. Il n'y a tout simplement aucun moyen pour le serveur de définir automatiquement l'en-tête d'authentification au nom du client.
Darrel Miller
1
merci pour la pointe Darrel. Avez-vous des exemples de ce à quoi cela pourrait ressembler sur asp.net? J'ai eu du mal avec cela pour mon monotouch et maintenant mon application Windows Store. Je serais heureux s'il y avait un moyen simple. C'est une douleur, en particulier avec async et attend maintenant sur les applications Windows Store.
Peter Kellner

Réponses:

170

Pour ajouter des cookies à une demande, remplissez le conteneur de cookies avant la demande avec CookieContainer.Add(uri, cookie). Une fois la demande effectuée, le conteneur de cookies sera automatiquement rempli avec tous les cookies de la réponse. Vous pouvez ensuite appeler GetCookies () pour les récupérer.

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
la source
8
Remarque: Après avoir reçu les cookies initiaux lors du premier appel, lors de l'accès à des pages du même domaine, les cookies seront envoyés automatiquement, aucune étape supplémentaire n'est nécessaire.
Jahmic
Vous devez ajouter "using System.linq;"
Cabuxa.Mapache
^^ System.Linq n'est requis que si vous souhaitez utiliser la méthode .Cast <>, ce n'est pas nécessaire pour la récupération des cookies, mais cela devrait être explicite :)
MikeDub
Est-il possible d'obtenir des cookies de la même manière si httpclientest construit à partir de l'usine httpclient? ie méthode de générateur ajoutée aux services.AddHttpClient
user3279954
sur get Async, nous avons déjà fait référence à "google.com", pourquoi devons-nous à nouveau déclarer un URI avec une référence?
Malcolm Salvador
7

Il existe une alternative si vous n'avez pas accès au HttpClientet que vous ne pouvez pas l'injecter CookieContainer. Cela fonctionne dans .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
la source
1
Brillant et brut mais juste ce dont j'ai besoin ... Bon travail, merci.
Vedran Mandić
5

Vous pouvez facilement obtenir une valeur de cookie avec l'URL donnée.

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
la source