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 avecHttpResponseMessage
, et en-têtes de contenu avec des objetsHttpContent
.
Comment puis-je définir l'en-tête Content-Type
dans un HttpClient
la demande?
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);
});
Pour ceux qui n'ont pas vu Johns commenter la solution de carlos ...
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
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
Essayez d'utiliser TryAddWithoutValidation
var client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
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.
. 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.
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!
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(...);
}
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.