En-tête personnalisé à la demande HttpClient

140

Comment ajouter un en-tête personnalisé à une HttpClientdemande? J'utilise une PostAsJsonAsyncméthode pour publier le JSON. L'en-tête personnalisé que j'aurais besoin d'être ajouté est

"X-Version: 1"

Voici ce que j'ai fait jusqu'à présent:

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
la source
3
Double
Liam
@Liam: Ma question était de savoir comment ajouter des en-têtes personnalisés. Où l'autre question était de savoir comment ajouter des en
Libin Joseph
2
Je pense qu'il a été constaté que nous ne devrions pas nous débarrasser de HttpClient. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Don Rolling

Réponses:

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
la source
38
La réponse est extrêmement déroutante ... pourquoi apportez-vous du code pour les documents, blank.pdf, etc.? instancier des classes bytearray pour passer des en-têtes personnalisés dans le paramètre Content?
heug
2
@heug Eh bien. Si vous recherchez un en-tête, vous pouvez le voir. Le contenu est présent ici afin de compléter l'image car vous souhaitez probablement ajouter du contenu à votre demande. Et pour ne pas être fastidieux, le contenu est compliqué et contient à la fois des données JSON et binaires.
Anubis
2
il semble juste plus simple de le faire comme ceci: créez StringContent en utilisant votre contenu JSON, créez un message HTTP avec votre méthode et URI, puis ajoutez des en-têtes comme message.Headers.Add ("x": "y") .... puis passez-les dans une réponse var comme "var response = await httpClient.SendAsync (message);"
heug
@heug Je m'en souviendrai pour le furute. Merci!
Anubis
3
Quelle ligne dans la réponse acceptée ci-dessus implémente réellement l'en-tête demandé par l'OP, X-Version? Pourquoi est-ce considéré comme la réponse acceptée?
Ron
215

J'ai trouvé la réponse à ma question.

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

Cela devrait ajouter un en-tête personnalisé à votre demande

Libin Joseph
la source
50
Non. Cette réponse doit être considérée avec prudence, car les en-têtes de demande par défaut sont envoyés avec chaque demande. Vous devriez construire votre requête comme @Anubis l'a suggéré. DefaultsRequestHeaders doit être renseigné lorsque vous créez le HttpClient.
Ruhrpottpatriot
6
Cela ne fonctionne que parce que vous instanciez un nouveau HttpClient pour chaque requête. Ce n'est pas ainsi que cette classe doit être utilisée: il doit s'agir d'un champ statique, réutilisé pour toutes les requêtes, du moins celles adressées au même endpoint. Consultez la documentation et les innombrables articles de blog disponibles. Ensuite, comme le souligne @Ruhrpottpatriot, la modification des en-têtes par défaut affectera toutes les requêtes.
kamilk
@Ruhrpottpatriot Quel est le problème avec l'envoi de l'en-tête pour chaque demande?
David Klempfner
1
@ajbeaven Non, ce n'est pas ce que ça dit. L'exemple en haut de la page montre la méthode Main de l'application, donc même si le HttpClient est supprimé, la même instance est utilisée pendant toute la durée de vie de l'application, et c'est correct en ce qui concerne ce que la documentation dit un peu un peu plus bas: «HttpClient est destiné à être instancié une fois et réutilisé tout au long de la vie d'une application» . À la suite de ce paragraphe, vous trouverez un exemple recommandant d'affecter un HttpClient à un champ statique.
kamilk
1
@kamilk, vous avez tout à fait raison - cet exemple me trompe. Merci de m'avoir
redonné
79

Voici une réponse basée sur celle d'Anubis (qui est une meilleure approche car elle ne modifie pas les en-têtes pour chaque requête) mais qui est plus équivalente au code de la question d'origine:

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
la source
@RossPresser certainement pas. Content-Type est un en-tête Content.
Panagiotis Kanavos
1
D'accord, c'est la réponse. Il montre comment ajouter l'en-tête demandé par OP. J'ai également répondu à ma question.
Ron
1
FYI je pense que HttpRequestHeader.Accessdevrait être HttpRequestHeader.Accept.
Mass Dot Net
qu'est-ce que svm au fait?
aswzen
@aswzen C'est de la question du PO - quelque chose de modèle, je suppose. L'objet en cours de sérialisation.
Chris Peacock
2

Il y a une Headerspropriété dans la HttpRequestMessageclasse. Vous pouvez y ajouter des en-têtes personnalisés, qui seront envoyés avec chaque requête HTTP. Le DefaultRequestHeadersdans la HttpClientclasse, en revanche, définit les en-têtes à envoyer avec chaque demande envoyée à l'aide de cet objet client, d'où le nom Default Request Headers.

J'espère que cela rend les choses plus claires, du moins pour quelqu'un qui verra cette réponse à l'avenir.

Bob le bricoleur
la source
1
Non, cela ne le rend pas plus clair. Dans les deux cas, vous dites que vous envoyez des en-têtes à chaque demande - Quelle est donc la différence?
joedotnot
3
Headersest une propriété d'un HttpRequestMessageobjet individuel . Ainsi, vous pouvez créer différents messages avec différents en-têtes. DefaultRequestHeadersest une propriété de l' HttpClientobjet; si plusieurs messages sont envoyés via un message donné HttpClient, tous ces messages auront tous le même DefaultRequestHeadersajouté aux en-têtes individuels du message.
Ross Presser