Encabezado personalizado para solicitud HttpClient

140

¿Cómo agrego un encabezado personalizado a una HttpClientsolicitud? Estoy usando el PostAsJsonAsyncmétodo para publicar el JSON. El encabezado personalizado que necesitaría agregar es

"X-Version: 1"

Esto es lo que he hecho hasta ahora:

using (var client = new HttpClient()) {
    client.BaseAddress = new Uri("https://api.clickatell.com/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "xxxxxxxxxxxxxxxxxxxx");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    var response = client.PostAsJsonAsync("rest/message", svm).Result;
}
Libin Joseph
fuente
3
Posible duplicado de Agregar encabezados HTTP a HttpClient
Liam
@Liam: Mi pregunta era cómo agregar encabezados personalizados. Donde como la otra pregunta era cómo agregar encabezados
Libin Joseph
2
Creo que se ha descubierto que no debemos deshacernos de HttpClient. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Don Rolling

Respuestas:

57
var request = new HttpRequestMessage {
    RequestUri = new Uri("[your request url string]"),
    Method = HttpMethod.Post,
    Headers = {
        { "X-Version", "1" } // HERE IS HOW TO ADD HEADERS,
        { HttpRequestHeader.Authorization.ToString(), "[your authorization token]" },
        { HttpRequestHeader.ContentType.ToString(), "multipart/mixed" },//use this content type if you want to send more than one content type
    },
    Content = new MultipartContent { // Just example of request sending multipart request
        new ObjectContent<[YOUR JSON OBJECT TYPE]>(
            new [YOUR JSON OBJECT TYPE INSTANCE](...){...}, 
            new JsonMediaTypeFormatter(), 
            "application/json"), // this will add 'Content-Type' header for the first part of request
        new ByteArrayContent([BINARY DATA]) {
            Headers = { // this will add headers for the second part of request
                { "Content-Type", "application/Executable" },
                { "Content-Disposition", "form-data; filename=\"test.pdf\"" },
            },
        },
    },
};
Anubis
fuente
38
la respuesta es extremadamente confusa ... ¿por qué traes código para documentos, blank.pdf, etc.? crear instancias de clases bytearray para pasar encabezados personalizados dentro del parámetro Content?
heug
2
@heug Bueno. Si está buscando un encabezado, puede verlo. El contenido está presente aquí para completar la imagen porque lo más probable es que desee agregar algo de contenido a su solicitud. Y para no ser tedioso, el contenido es complicado y contiene datos JSON y binarios.
Anubis
2
parece más sencillo hacerlo así: cree StringContent usando su contenido JSON, cree un mensaje HTTP con su método y URI, luego agregue encabezados como message.Headers.Add ("x": "y") ... luego pasarlos a una respuesta var como "var response = await httpClient.SendAsync (mensaje);"
heug
@heug Recordaré esto para el furute. ¡Gracias!
Anubis
3
¿Qué línea en la respuesta aceptada anterior implementa realmente el encabezado que solicitó el OP, X-Version? ¿Por qué se considera esto la respuesta aceptada?
Ron
215

He encontrado la respuesta a mi pregunta.

client.DefaultRequestHeaders.Add("X-Version","1");

Eso debería agregar un encabezado personalizado a su solicitud

Libin Joseph
fuente
50
No, no lo hace. Esta respuesta debe considerarse con precaución, ya que los encabezados de solicitud predeterminados se envían con cada solicitud. Debe compilar su solicitud como @Anubis sugirió. DefaultsRequestHeaders debe rellenarse al crear el HttpClient.
Ruhrpottpatriot
66
Esto solo funciona porque está creando instancias de un nuevo HttpClient para cada solicitud. Esta no es la forma en que se debe usar esta clase: debe ser un campo estático, reutilizado para todas las solicitudes, al menos para el mismo punto final. Ver documentación e innumerables publicaciones de blog por ahí. Luego, como por supuesto, como señala @Ruhrpottpatriot, cambiar los encabezados predeterminados afectará a todas las solicitudes.
kamilk
@Ruhrpottpatriot ¿Qué tiene de malo enviar el encabezado de cada solicitud?
David Klempfner
1
@ajbeaven No, eso no es lo que dice. El ejemplo en la parte superior de la página muestra el método Principal de la aplicación, por lo que, aunque se elimine el HttpClient, la misma instancia se usa durante toda la vida útil de la aplicación, y eso es correcto con respecto a lo que la documentación dice un poco un poco más abajo: 'HttpClient está destinado a ser instanciado una vez y reutilizado durante la vida útil de una aplicación' . A continuación de este párrafo hay un ejemplo que recomienda asignar un HttpClient a un campo estático.
kamilk
1
@kamilk, tienes toda la razón, ese ejemplo me puso mal. Gracias por ponerme bien :)
ajbeaven
79

Aquí hay una respuesta basada en eso de Anubis (que es un mejor enfoque ya que no modifica los encabezados para cada solicitud) pero que es más equivalente al código en la pregunta original:

using Newtonsoft.Json;
...

    var client = new HttpClient();
    var httpRequestMessage = new HttpRequestMessage
        {
            Method = HttpMethod.Post,
            RequestUri = new Uri("https://api.clickatell.com/rest/message"),
            Headers = { 
                { HttpRequestHeader.Authorization.ToString(), "Bearer xxxxxxxxxxxxxxxxxxxx" },
                { HttpRequestHeader.Accept.ToString(), "application/json" },
                { "X-Version", "1" }
            },
            Content = new StringContent(JsonConvert.SerializeObject(svm))
        };

    var response = client.SendAsync(httpRequestMessage).Result;
Chris Peacock
fuente
@RossPresser definitivamente no. Content-Type es un encabezado de contenido.
Panagiotis Kanavos
1
De acuerdo, esta es la respuesta. Muestra cómo agregar el encabezado que OP solicitó. Respondí mi pregunta también.
Ron
1
FYI creo que HttpRequestHeader.Accessdebería ser HttpRequestHeader.Accept.
Mass Dot Net
¿Qué es svm por cierto?
aswzen
@aswzen Es de la pregunta del OP, algo que supongo. El objeto que se serializa.
Chris Peacock
2

Hay una Headerspropiedad en la HttpRequestMessageclase. Puede agregar encabezados personalizados allí, que se enviarán con cada solicitud HTTP. En DefaultRequestHeadersla HttpClientclase, por otro lado, establece los encabezados que se enviarán con cada solicitud enviada utilizando ese objeto de cliente, de ahí el nombre Encabezados de solicitud predeterminados .

Espero que esto aclare las cosas, al menos para alguien que vea esta respuesta en el futuro.

Bob el Constructor
fuente
1
No, no lo aclara más. En ambos casos, está diciendo que está enviando encabezados en cada solicitud. Entonces, ¿cuál es la diferencia?
joedotnot
3
Headerses una propiedad de un HttpRequestMessageobjeto individual . Por lo tanto, puede crear diferentes mensajes con diferentes encabezados. DefaultRequestHeaderses una propiedad del HttpClientobjeto; Si se envían varios mensajes a través de un determinado HttpClient, todos estos mensajes tendrán el mismo DefaultRequestHeadersagregado a los encabezados individuales del mensaje.
Ross Presser