POST JsonObject avec HttpClient à partir de l'API Web


288

J'essaie de POSTER une JsonObjectutilisation à HttpClientpartir de l'API Web. Je ne suis pas sûr de savoir comment procéder et je ne trouve pas grand-chose dans l'exemple de code.

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

var myObject = (dynamic)new JsonObject();
myObject.Data = "some data";
myObject.Data2 = "some more data";

HttpClient httpClient = new HttpClient("myurl");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

HttpResponseMessage response = httpClient.Post("", ???);

Je pense que j'ai besoin de me lancer en JsonObjecttant que StreamContentmais je suis accroché à cette étape.

Réponses:


440

Avec la nouvelle version de HttpClientet sans le WebApipackage, ce serait:

var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
var result = client.PostAsync(url, content).Result;

Ou si vous le souhaitez async:

var result = await client.PostAsync(url, content);

3
Ce constructeur StringContent surchargé a fait l'affaire pour moi.
Captain Kenpachi

23
Réfléchissez bien avant d'appeler Result sur une méthode Async via blog.stephencleary.com/2012/07/07/dont-block-on-async-code.html
Ruchira

2
Pour tous ceux qui ont été tentés de jeter ceci usingcomme j'étais: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

J'ai mis un usingautour de la StringContentcréation cependant.
bcr

En utilisant cette réponse, je recevais toujours une réponse "400 Bad Request" d'une API à laquelle je POSTAISais ma demande JSON (Visual Studio 2017, .NET 4.6.2). En plus var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json")je devais régler content.Headers.ContentType = new MediaTypeHeaderValue("application/json");. Voir la réponse ci-dessous pour plus de détails.
anthls

161

La manière la plus simple consiste à utiliser a StringContent, avec la représentation JSON de votre objet JSON.

httpClient.Post(
    "",
    new StringContent(
        myObject.ToString(),
        Encoding.UTF8,
        "application/json"));

14
Prenez note du type de contenu. Je l'ai laissé de côté et m'a fait déboguer beaucoup plus longtemps que je ne le souhaiterais.
Zapnologica

Ne devriez-vous pas cependant supprimer l'instance de StringContent?
Phil Haselden

63

Selon votre version .NET, vous pouvez également utiliser la HttpClientExtensions.PostAsJsonAsyncméthode.

https://msdn.microsoft.com/en-us/library/system.net.http.httpclientextensions.postasjsonasync.aspx


4
Maintenant trouvé dans Microsoft.AspNet.Client.WebApi nuget
jle

2
Je viens de l'installer à partir de Microsoft.AspNet.WebApi.Client
Adriaan Davel

Cela a résolu mon problème. Je m'amusais depuis (longtemps) en passant une classe C # qui contenait certaines propriétés qui étaient des listes utilisant client.PostAsync, client.SendAsync .. J'obtenais des résultats très mitigés. Si le tableau était vide, ma solution API le récupérait, mais si le tableau avait un élément, la méthode du contrôleur n'était pas en mesure de modéliser le JSON. Merci pour cela. Il me semble que PostAsJsonAsync convertit de manière plus fiable un objet C # complexe en JSON.
Franklin Tarter

Existe-t-il un package nuget pour cela? Je déteste quand je transfère le projet sur une nouvelle machine, et cette référence est toujours manquante.
Zapnologica


51

Si vous utilisez Newtonsoft.Json:

using Newtonsoft.Json;
using System.Net.Http;
using System.Text;

public static class Extensions
{
    public static StringContent AsJson(this object o)
        => new StringContent(JsonConvert.SerializeObject(o), Encoding.UTF8, "application/json");
}

Exemple:

var httpClient = new HttpClient();
var url = "https://www.duolingo.com/2016-04-13/login?fields=";
var data = new { identifier = "username", password = "password" };
var result = await httpClient.PostAsync(url, data.AsJson())

ce n'est pas spécifique au noyau asp.net, il est même générique jusqu'à 4.5.6
danatcofo

JsonConvert.SerializeObjectproblèmes avec DateTimes ISO 8601 Type: Local ou UTC ... hackered.co.uk/articles/…
Kiquenet

21

Je n'ai pas assez de réputation pour ajouter un commentaire sur la réponse de Pomber donc je poste une autre réponse. En utilisant l'approche de pomber, j'ai continué à recevoir une réponse "400 Bad Request" d'une API à laquelle je POSTAISais ma demande JSON (Visual Studio 2017, .NET 4.6.2). Finalement, le problème a été attribué à l'en-tête "Content-Type" produit par StringContent () étant incorrect (voir https://github.com/dotnet/corefx/issues/7864 ).

tl; dr

Utilisez la réponse du bombardier avec une ligne supplémentaire pour définir correctement l'en-tête de la demande:

var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var result = client.PostAsync(url, content).Result;

Merci, anthls. var content = new StringContent (jsonObject.ToString (), Encoding.UTF8, "application / json") n'était pas suffisant. Il a besoin de content.Headers.ContentType = new MediaTypeHeaderValue ("application / json"); Merci d'avoir sauvé ma raison.
Gail Foad

1
Cela a très bien fonctionné. Une raison pour laquelle "application / json" doit être définie deux fois, une dans le constructeur et une fois via la propriété? Est-ce un bug?
Festus Martingale

@FestusMartingale: bonne question! D'après ma lecture du problème github (lié dans la réponse), le passage de "application/json"dans le StringContentconstructeur n'est probablement pas nécessaire car il est explicitement défini sur la content.Headers.ContentTypepropriété résultante . Cependant, je n'ai pas testé cela dans le code.
anthls

Il semble que le serveur ne prenne pas en charge la chaîne de type de contenu complet. Lorsque vous utilisez le constructeur sans remplacer le ContentType, il définit la valeur comme application/json; charset=utf-8.
Bertm13

2

le code dessus dans vbnet:

dim FeToSend as new (object--> define class)

Dim client As New HttpClient
Dim content = New StringContent(FeToSend.ToString(), Encoding.UTF8,"application/json")
content.Headers.ContentType = New MediaTypeHeaderValue( "application/json" )
Dim risp = client.PostAsync(Chiamata, content).Result

msgbox(risp.tostring)

J'espère que cette aide

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.