J’essaie de définir l’en Content-Type
tête Content-Type
d’un object HttpClient
comme requirejs par une API que HttpClient
.
J’ai essayé de définir le type de 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"); // ... }
Cela me permet d’append l’en-tête Accept
mais lorsque j’essaie d’append Content-Type
il génère 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
, les en-têtes de réponse avecHttpResponseMessage
et les en-têtes de contenu avec des objectsHttpContent
.
Comment puis-je définir l’en Content-Type
tête Content-Type
dans une requête HttpClient
?
Le type de contenu est un en-tête du contenu et non de la demande, ce qui explique son échec. AddWithoutValidation
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 (notez que l’extrait de code ajoute “application / json” dans deux emplacements 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 SsortingngContent("{\"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 carlos solution …
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
Si cela ne vous dérange pas une petite dépendance à la bibliothèque, Flurl.Http [divulgation: je suis l’auteur] rend cette tâche très simple. Sa méthode PostJsonAsync
prend en charge à la fois la sérialisation du contenu et la définition de l’ content-type
tête content-type
, et ReceiveJson
désérialise la réponse. Si l’en-tête d’ accept
est requirejs, vous devez le définir vous-même, mais Flurl offre une méthode assez simple pour le faire:
using Flurl.Http; var result = await "http://example.com/" .WithHeader("Accept", "application/json") .PostJsonAsync(new { ... }) .ReceiveJson();
Flurl utilise HttpClient et Json.NET sous le capot, et il s’agit d’une PCL qui fonctionnera sur diverses plates-formes.
PM> Install-Package Flurl.Http
essayez d’utiliser TryAddWithoutValidation
var client = new HttpClient(); client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
Appelez AddWithoutValidation
au lieu de Add
(voir ce lien MSDN ).
Sinon, je suppose que l’API que vous utilisez n’a besoin que de cela pour les requêtes POST ou PUT (pas les requêtes GET ordinaires). Dans ce cas, lorsque vous appelez HttpClient.PostAsync
et que vous transmettez un HttpContent
, définissez-le sur la propriété Headers
de cet object HttpContent
.
.Net essaie de vous forcer à respecter certaines normes, à savoir que l’en Content-Type
tête Content-Type
ne peut être spécifié que pour les requêtes qui ont du contenu (par exemple, POST
, PUT
, etc.). Par conséquent, comme d’autres l’ont indiqué, la méthode préférée pour définir l’en Content-Type
tête Content-Type
passe par la propriété HttpContent.Headers.ContentType
.
Cela étant dit, certaines API (telles que LiquidFiles Api , à partir du 19/12/2016) nécessitent de définir l’en Content-Type
tête Content-Type
pour une requête GET
. .Net ne permettra pas de définir cet en-tête sur la demande elle-même – même en utilisant TryAddWithoutValidation
. De plus, vous ne pouvez pas spécifier un Content
pour la demande, même s’il est de longueur nulle. La seule façon de contourner cela était de recourir à la reflection. Le code (au cas où une autre en aurait 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)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 les différentes versions de la DLL. Dans le code source sur GitHub , le champ est actuellement nommé s_invalidHeaders
. L’exemple a été modifié pour en tenir compte selon la suggestion de @David Thompson.
Quelques informations supplémentaires sur .NET Core (après avoir lu la publication d’erdomke sur la définition d’un champ privé pour fournir le type de contenu sur une requête sans contenu) …
Après avoir débogué mon code, je ne peux pas voir le champ privé définir via la reflection – alors j’ai pensé essayer 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 SsortingngContent(ssortingng.Empty, Encoding.UTF8, "application/json"); HttpClient client = new HttpClient(); Task response = client.SendAsync(httpRequest); //I know I should have used async/await here! var result = response.Result;
Et, comme prévu, je reçois une exception globale avec le contenu "Cannot send a content-body with this verb-type."
Cependant, si je fais la même chose avec .NET Core (1.1) – je ne reçois pas d’exception. Ma demande de serveur a été très satisfaisante, et le type de contenu a été choisi.
Cela m’a agréablement surpris et j’espère que cela aidera quelqu’un!
Ok, ce n’est pas HTTPClient mais si vous pouvez l’utiliser, WebClient est assez simple:
using (var client = new System.Net.WebClient()) { client.Headers.Add("Accept", "application/json"); client.Headers.Add("Content-Type", "application/json; charset=utf-8"); client.DownloadSsortingng(...); }
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.