POST JsonObject con HttpClient dall'API Web


289

Sto cercando di postare un JsonObjectutilizzo HttpClientdall'API Web. Non sono del tutto sicuro di come procedere e non riesco a trovare molto nel modo del codice di esempio.

Ecco cosa ho finora:

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("", ???);

Penso di aver bisogno di lanciare il mio JsonObjectcome un StreamContentma mi sto impiccando su quel passaggio.

Risposte:


443

Con la nuova versione di HttpCliente senza il WebApipacchetto sarebbe:

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

O se lo vuoi async:

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

3
Quel costruttore StringContent sovraccarico ha fatto il trucco per me.
Capitano Kenpachi,

23
Pensaci due volte prima di chiamare il risultato su un metodo asincrono sebbene blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Ruchira,

2
Per chiunque sia stato tentato di lanciarlo in un modo usingsimile a me: aspnetmonsters.com/2016/08/2016 08-08-27
httpclientwrong

Ho messo un usingintorno alla StringContentcreazione però.
bcr

1
Usando questa risposta ho continuato a ricevere una risposta "400 Bad Request" da un'API a cui stavo inviando la mia richiesta JSON (Visual Studio 2017, .NET 4.6.2). Inoltre var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json")ho dovuto impostare content.Headers.ContentType = new MediaTypeHeaderValue("application/json");. Vedi la risposta sotto per maggiori dettagli.
anthls,

161

Il modo più semplice è usare un StringContent, con la rappresentazione JSON dell'oggetto JSON.

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

14
Prendi nota del tipo di contenuto. L'ho lasciato fuori e mi ha fatto il debug per molto più tempo di quanto vorrei.
Zapnologica,

Non dovresti comunque eliminare l'istanza StringContent?
Phil Haselden,

63

A seconda della versione di .NET è possibile utilizzare anche il HttpClientExtensions.PostAsJsonAsyncmetodo.

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


4
Ora trovato in Microsoft.AspNet.Client.WebApi nuget
jle

2
L'ho appena installato da Microsoft.AspNet.WebApi.Client
Adriaan Davel

Questo ha risolto il mio problema. Stavo scherzando per un (lungo) mentre passavo una classe C # che conteneva alcune proprietà che erano Elenchi usando client.PostAsync, client.SendAsync .. Stavo ottenendo risultati molto contrastanti. Se l'array fosse vuoto, la mia soluzione API lo prenderebbe, ma se l'array avesse un elemento il metodo controller non era in grado di modellare il JSON. Grazie per questo. Mi sembra che PostAsJsonAsync converta in modo più affidabile un oggetto C # complesso in JSON.
Franklin Tarter,

Esiste un pacchetto nuget per questo? Lo odio quando trasferisco il progetto su una nuova macchina e questo riferimento manca sempre.
Zapnologica,


51

Se si utilizza 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");
}

Esempio:

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())

questo non è specifico del core asp.net, è in realtà generico fino a 4.5.6
danatcofo

JsonConvert.SerializeObjectproblemi con DateTimes ISO 8601 tipo: locale o UTC ... hackered.co.uk/articles/…
Kiquenet

21

Non ho abbastanza reputazione per aggiungere un commento sulla risposta di Pomber, quindi sto postando un'altra risposta. Usando l'approccio di pomber ho continuato a ricevere una risposta "400 Bad Request" da un'API a cui stavo inviando la mia richiesta JSON (Visual Studio 2017, .NET 4.6.2). Alla fine il problema è stato rintracciato nell'intestazione "Content-Type" prodotta da StringContent () non corretta (consultare https://github.com/dotnet/corefx/issues/7864 ).

tl; dr

Usa la risposta di pomber con una riga aggiuntiva per impostare correttamente l'intestazione sulla richiesta:

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

Grazie, Anthls. var content = new StringContent (jsonObject.ToString (), Encoding.UTF8, "application / json") non era sufficiente. Richiede content.Headers.ContentType = new MediaTypeHeaderValue ("application / json"); Grazie per avermi salvato la sanità mentale.
Gail Foad,

1
Questo ha funzionato alla grande. Qual è il motivo per cui "application / json" deve essere impostato due volte, uno nel costruttore e una volta tramite la proprietà? E 'un errore?
Festus Martingale,

@FestusMartingale: bella domanda! Dalla mia lettura del problema github (collegato nella risposta) il passaggio di "application/json"nel StringContentcostruttore probabilmente non è richiesto in quanto viene esplicitamente impostato sulla content.Headers.ContentTypeproprietà risultante . Tuttavia, non ho provato questo nel codice.
Anthls,

Sembra che il server non supporti la stringa del tipo di contenuto completo. Quando si utilizza il costruttore senza sovrascrivere ContentType, imposta il valore come application/json; charset=utf-8.
Bertm13

2

il codice su di esso in 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)

Spero che questo aiuto

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.