Comment définissez-vous L'en-tête Content-Type Pour une requête HttpClient?

J'essaie de définir l'en-tête Content-Type d'un objet HttpClient comme requis par une API que j'appelle.

J'ai essayé de définir le Content-Type comme ci-dessous:

using (var httpClient = new HttpClient())
{
    httpClient.BaseAddress = new Uri("http://example.com/");
    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
    // ...
}

, Il me permet d'ajouter le Accept - tête, mais lorsque j'essaie d'ajouter Content-Type, il jette l'exception suivante:

Nom D'en-tête mal utilisé. Assurez-vous que les en-têtes de requête sont utilisés avec HttpRequestMessage, en-têtes de réponse avec HttpResponseMessage, et en-têtes de contenu avec des objets HttpContent.

Comment puis-je définir l'en-tête Content-Type dans un HttpClient la demande?

498
demandé sur Nikolai Samteladze 2012-05-21 07:29:17

9 réponses

Le type de contenu est un en-tête du contenu, Pas de la requête, c'est pourquoi cela échoue. {[1] } comme suggéré par Robert Levy peut fonctionner, mais vous pouvez également définir le type de contenu lors de la création du contenu de la requête lui-même (notez que l'extrait de code ajoute "application / json" à deux endroits-pour les en-têtes Accept et Content-Type):

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://example.com/");
client.DefaultRequestHeaders
      .Accept
      .Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "relativeAddress");
request.Content = new StringContent("{\"name\":\"John Doe\",\"age\":33}",
                                    Encoding.UTF8, 
                                    "application/json");//CONTENT-TYPE header

client.SendAsync(request)
      .ContinueWith(responseTask =>
      {
          Console.WriteLine("Response: {0}", responseTask.Result);
      });
618
répondu carlosfigueira 2018-02-13 04:39:08

Pour ceux qui n'ont pas vu Johns commenter la solution de carlos ...

req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
107
répondu archgl 2014-05-05 15:38:43

Si cela ne vous dérange pas une petite dépendance de bibliothèque, Flurl.Http [divulgation: je suis l'auteur] rend ce Uber-simple. Sa méthode PostJsonAsync prend en charge à la fois la sérialisation du contenu et la définition de l'en-tête content-type, et ReceiveJson désérialise la réponse. Si l'en-tête accept est requis, vous devrez le définir vous-même, mais Flurl fournit un moyen assez propre de le faire aussi:

using Flurl.Http;

var result = await "http://example.com/"
    .WithHeader("Accept", "application/json")
    .PostJsonAsync(new { ... })
    .ReceiveJson<TResult>();

Flurl utilise HttpClient et Json.NET sous le capot, et c'est un PCL donc ça va fonctionner sur une variété de plate.

PM> Install-Package Flurl.Http
42
répondu Todd Menier 2018-06-19 14:15:11

Essayez d'utiliser TryAddWithoutValidation

  var client = new HttpClient();
  client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
27
répondu SharpCoder 2015-11-19 22:48:39

Appel de AddWithoutValidation au lieu de Add (voir ce lien MSDN).

Alternativement, je suppose que l'API que vous utilisez ne l'exige vraiment que pour les requêtes POST ou PUT (pas les requêtes GET ordinaires). Dans ce cas, lorsque vous appelez HttpClient.PostAsync et passez un HttpContent, régler cela sur l' Headers la propriété de HttpContent objet.

15
répondu Robert Levy 2013-08-08 18:00:02

. Net essaie de vous forcer à obéir à certaines normes, à savoir que l'en-tête Content-Type ne peut être spécifié que sur les requêtes contenant du contenu (par exemple POST, PUT, etc.). Par conséquent, comme d'autres l'ont indiqué, la manière préférée de définir l'en-tête Content-Type est de HttpContent.Headers.ContentType propriété.

Cela dit, certaines API (telles que L'Api LiquidFiles, à partir du 2016-12-19) nécessitent de définir l'en-tête Content-Type pour une requête GET. . Net ne permettra pas de définir cet en-tête sur le demande elle-même - même en utilisant TryAddWithoutValidation. De plus, vous ne pouvez pas spécifier un Content pour la requête-même si elle est de longueur nulle. La seule façon dont je pouvais sembler contourner cela était de recourir à la réflexion. Le code (au cas où certains en auraient besoin) est

var field = typeof(System.Net.Http.Headers.HttpRequestHeaders)
    .GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static) 
  ?? typeof(System.Net.Http.Headers.HttpRequestHeaders) 
    .GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
  var invalidFields = (HashSet<string>)field.GetValue(null);
  invalidFields.Remove("Content-Type");
}
_client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");

Modifier:

Comme indiqué dans les commentaires, Ce champ a des noms différents dans différentes versions de la dll. Dans le code source sur GitHub , le champ est actuellement nommé s_invalidHeaders. L'exemple a été modifiée pour tenir compte de cela par la suggestion de @David Thompson.

15
répondu erdomke 2017-03-31 15:19:26

Quelques informations supplémentaires sur. net Core (après avoir lu le post d'erdomke sur la définition d'un champ privé pour fournir le type de contenu sur une requête qui n'a pas de contenu)...

Après avoir débogué mon code, je ne peux pas voir le champ privé à définir via la réflexion-donc j'ai pensé que j'essaierais de recréer le problème.

J'ai essayé le code suivant en utilisant. Net 4.6:

HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, @"myUrl");
httpRequest.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpClient client = new HttpClient();
Task<HttpResponseMessage> response =  client.SendAsync(httpRequest);  //I know I should have used async/await here!
var result = response.Result;

Et, comme prévu, j'obtiens une exception agrégée avec le contenu "Cannot send a content-body with this verb-type."

Cependant, si je fais le même chose avec. net Core (1.1) - Je ne reçois pas d'exception. ma demande a été très heureusement répondu par mon application serveur, et le type de contenu a été ramassé.

J'ai été agréablement surpris à ce sujet, et j'espère que cela aide quelqu'un!

12
répondu Jay 2017-06-12 09:06:34

Ok, ce N'est pas HTTPClient mais si vous pouvez l'utiliser, WebClient est assez facile:

using (var client = new System.Net.WebClient())
 {
    client.Headers.Add("Accept", "application/json");
    client.Headers.Add("Content-Type", "application/json; charset=utf-8");
    client.DownloadString(...);
 }
2
répondu Ziba Leah 2018-07-09 20:21:33
var content = new HttpContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", "utf-8"));
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("IEEE754Compatible", "true"));

C'est tout ce dont vous avez besoin.

1
répondu user3556671 2018-05-28 14:03:19