Agregar encabezados cuando se usa httpClient.GetAsync

152

Estoy implementando una API hecha por otros colegas con Apiary.io, en un proyecto de aplicación de la Tienda Windows.

Muestran este ejemplo de un método que tengo que implementar:

var baseAddress = new Uri("https://private-a8014-xxxxxx.apiary-mock.com/");

using (var httpClient = new HttpClient{ BaseAddress = baseAddress })
{
    using (var response = await httpClient.GetAsync("user/list{?organizationId}"))
    {
        string responseData = await response.Content.ReadAsStringAsync();
    }
}

En este y en algunos otros métodos, necesito tener un encabezado con un token que obtengo antes.

Aquí hay una imagen de Postman (extensión de Chrome) con el encabezado del que estoy hablando: ingrese la descripción de la imagen aquí

¿Cómo agrego ese encabezado de autorización a la solicitud?

Ric
fuente
2
posible duplicado del encabezado de autorización
Daniel Kelley
55
Advertencia Para posibles buscadores de códigos: ¡este es un uso incorrecto de HttpClient! Consulte aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong por qué.
321X

Respuestas:

174

Cuando use GetAsync con el HttpClient, puede agregar los encabezados de autorización de la siguiente manera:

httpClient.DefaultRequestHeaders.Authorization 
                         = new AuthenticationHeaderValue("Bearer", "Your Oauth token");

Esto agrega el encabezado de autorización para la vida útil del HttpClient, por lo que es útil si accede a un sitio donde el encabezado de autorización no cambia.

Aquí hay una respuesta SO detallada

kmcnamee
fuente
31
-1 porque HttpClient debe ser reutilizable (ver aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong ). Si debe ser reutilizable, establecer los encabezados de solicitud predeterminados es una mala práctica.
JCKödel
23
@ JCKödel Esa es una suposición falsa que estás haciendo. Si siempre llama al mismo sitio con las mismas credenciales durante toda la vida útil del HttpClient utilizando DefaultRequestHeaders, no tendrá que volver a configurarlos continuamente con los mismos valores. Debería volver a leer el artículo que habla sobre el uso de la misma instancia del HttpClient, no hace declaraciones sobre que los encabezados de solicitud predeterminados sean una mala práctica. Si solo llamo a un sitio con el cliente HTTP, lo que en la práctica sucede usando DefaultRequestHeaders le evita tener que configurarlos cada vez.
kmcnamee
@ JCKödel, aunque usted es incorrecto en su suposición, voté por su comentario porque mencionó un punto importante. Se agregó mayor claridad a la respuesta.
Najeeb
@kmcnamee, ¿y si necesito pasar dos tokens?
Najeeb
281

Una respuesta posterior, pero porque nadie dio esta solución ...

Si no desea establecer el encabezado en la HttpClientinstancia agregándolo al DefaultRequestHeaders, puede establecer encabezados por solicitud .

Pero estará obligado a utilizar el SendAsync()método.

Esta es la solución correcta si desea reutilizarHttpClient , lo cual es una buena práctica para

Úselo así:

using (var requestMessage =
            new HttpRequestMessage(HttpMethod.Get, "https://your.site.com"))
{
    requestMessage.Headers.Authorization =
        new AuthenticationHeaderValue("Bearer", your_token);
    httpClient.SendAsync(requestMessage);
}
Philippe
fuente
55
Parece más seguro no usar DefaultRequestHeaders si el valor cambia con frecuencia.
Jason Rowe
3
Tenga en cuenta que es muy probable que necesite requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", your_token);"Portador" sería un encabezado HTTP no válido
Chris Marisic
3
Gracias por esto, estamos reutilizando nuestro HttpClient y esto nos ayudó
StevenMcD
2
@JCKodel habría añadido ruido porque usted no es necesaria la obligación de uso using, pero podría crear una instancia en el constructor y botar en elDispose()
Philippe
3
Nunca dije usar usingen HttpClient (esto es malo), dije en HttpRequesMessage (porque tiene buffers de memoria no administrados para la transmisión que DEBEN eliminarse después del uso). La solicitud y la respuesta son y deben desecharse en cada solicitud (de lo contrario, mantendrá bloqueados grandes bloques de memoria durante mucho tiempo). El HttpClientes reutilizable, hasta cierto punto.
JCKödel
70

La respuesta aceptada funciona, pero puede complicarse cuando quería intentar agregar encabezados Aceptar. Esto es con lo que terminé. Me parece más simple, así que creo que me quedaré con eso en el futuro:

client.DefaultRequestHeaders.Add("Accept", "application/*+xml;version=5.1");
client.DefaultRequestHeaders.Add("Authorization", "Basic " + authstring);
sirdank
fuente
La forma más sencilla de agregar encabezado de autorización básica
sandyiit
7

Puede agregar cualquier encabezado que necesite al HttpClient.

Aquí hay un buen tutorial al respecto.

Esto no solo hace referencia a solicitudes POST, también puede usarlo para solicitudes GET.

Greenhoorn
fuente
URL de Github , en caso de que el enlace del sitio expire.
Sen Jacob
5

Siguiendo la respuesta de greenhoorn, puede usar "Extensiones" de esta manera:

  public static class HttpClientExtensions
    {
        public static HttpClient AddTokenToHeader(this HttpClient cl, string token)
        {
            //int timeoutSec = 90;
            //cl.Timeout = new TimeSpan(0, 0, timeoutSec);
            string contentType = "application/json";
            cl.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
            cl.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", token));
            var userAgent = "d-fens HttpClient";
            cl.DefaultRequestHeaders.Add("User-Agent", userAgent);
            return cl;
        }
    }

Y use:

string _tokenUpdated = "TOKEN";
HttpClient _client;
_client.AddTokenToHeader(_tokenUpdated).GetAsync("/api/values")
RDyego
fuente
-1

A veces, solo necesitas este código.

 httpClient.DefaultRequestHeaders.Add("token", token);
Jackdon Wang
fuente