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.

marque
la source

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);
bombardier
la source
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"));
carlosfigueira
la source
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

user3285954
la source
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
Vous cherchez ceci ou autre chose? nuget.org/packages/Microsoft.AspNet.WebApi.Client
user3285954
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())
Matthew Steven Monkan
la source
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;
anthls
la source
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

Stefano Ronchese
la source