Luchando tratando de sacar la cookie de respuesta con HttpClient en .net 4.5

107

Tengo el siguiente código que funciona correctamente. No puedo averiguar cómo sacar la cookie de la respuesta. Mi objetivo es poder establecer cookies en la solicitud y obtener cookies de la respuesta. Pensamientos

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

Aquí está la respuesta 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
fuente
Por curiosidad, ¿puedo preguntarle por qué quiere leer las cookies en el cliente? Tengo entendido que las cookies se utilizan para enviar información al servidor, no para devolver información.
Darrel Miller
Utilizo la cookie devuelta en llamadas que devuelven JSON para no tener que hacer una llamada de autorización por separado para cada llamada JSON. Es decir, tengo un registro de llamadas / Home / GetData que devuelve JSON pero solo si está autorizado. En la solicitud del cliente, agrego la cookie para que / Home / GetData responda. De lo contrario, dirá "403" no autorizado.
Peter Kellner
Establecer el encabezado de autorización como encabezado predeterminado es casi tan efectivo y un poco más estándar. Simplemente no hay forma de que el servidor establezca el encabezado de autenticación automáticamente en nombre del cliente.
Darrel Miller
1
gracias por la propina Darrel. ¿Tiene algún ejemplo de cómo podría verse en asp.net? Luché con esto para mi monotouch y ahora mi aplicación de Windows Store. Sería feliz si hubiera una forma sencilla. Esto es una molestia, especialmente con async y await ahora en las aplicaciones de la tienda de Windows.
Peter Kellner

Respuestas:

170

Para agregar cookies a una solicitud, complete el contenedor de cookies antes de la solicitud con CookieContainer.Add(uri, cookie). Una vez realizada la solicitud, el contenedor de cookies se completará automáticamente con todas las cookies de la respuesta. Luego puede llamar a GetCookies () para recuperarlos.

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
fuente
8
Nota: Después de recibir las cookies iniciales en la primera llamada, al acceder a cualquier página del mismo dominio, las cookies se enviarán automáticamente, sin necesidad de pasos adicionales.
Jahmic
Debe agregar "using System.linq;"
Cabuxa.Mapache
^^ System.Linq solo es necesario si desea utilizar el método .Cast <>, no es necesario para la recuperación de cookies, pero esto debería explicarse por sí mismo :)
MikeDub
¿Es posible obtener cookies de la misma manera si httpclientse construye a partir de la fábrica httpclient? es decir, método de construcción agregado a services.AddHttpClient
user3279954
al obtener Async, ya hicimos una referencia a "google.com", ¿por qué necesitamos declarar un URI con una referencia a él nuevamente?
Malcolm Salvador
7

Existe una alternativa si no tiene acceso al HttpClient y no puede inyectar el CookieContainer. Esto funciona en .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
fuente
1
Brillante y crudo, pero justo lo que necesito ... Buen trabajo, gracias.
Vedran Mandić
5

Puede obtener fácilmente un valor de cookie con la URL dada.

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
fuente