POSTing JsonObject za pomocą HttpClient From Web API


289

Próbuję POST użyć JsonObjectprzy użyciu HttpClientinterfejsu API sieci Web. Nie jestem do końca pewien, jak sobie z tym poradzić i nie mogę znaleźć wiele na drodze do przykładowego kodu.

Oto co mam do tej pory:

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

Myślę, że muszę rzucić JsonObjectna siebie, StreamContentale jestem zawieszony na tym kroku.

Odpowiedzi:


441

W nowej wersji pakietu HttpClienti bez WebApiniego będzie to:

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

Lub jeśli chcesz async:

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

3
Ten przeciążony konstruktor StringContent załatwił sprawę.
Kapitan Kenpachi

23
Zastanów się dwa razy, zanim wywołasz
Ruchira

2
Dla każdego, kto miał ochotę rzucić to w usingpodobny sposób, byłem: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

I umieścić usingwokół StringContenttworzenia chociaż.
bcr

Korzystając z tej odpowiedzi, ciągle otrzymywałem odpowiedź „400 Błędne żądanie” z interfejsu API, do którego wysyłałem moje zapytanie JSON (Visual Studio 2017, .NET 4.6.2). Poza var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json")tym musiałem ustawić content.Headers.ContentType = new MediaTypeHeaderValue("application/json");. Zobacz odpowiedź poniżej, aby uzyskać więcej informacji.
mrówki

161

Najłatwiejszym sposobem jest użycie StringContentz reprezentacją JSON obiektu JSON.

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

14
Zwróć uwagę na typ zawartości. Zostawiłem to i kazałem debugować o wiele dłużej niż chciałbym.
Zapnologica

Nie powinieneś jednak usuwać instancji StringContent?
Phil Haselden

63

W zależności od wersji .NET możesz także użyć HttpClientExtensions.PostAsJsonAsyncmetody.

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


4
Teraz znajduje się w Microsoft.AspNet.Client.WebApi
nuget

2
Właśnie zainstalowałem go z Microsoft.AspNet.WebApi.Client
Adriaan Davel

To rozwiązało mój problem. Mieszałem się (długo), przekazując klasę C # zawierającą niektóre właściwości, które były Listami za pomocą client.PostAsync, client.SendAsync .. Otrzymałem bardzo mieszane wyniki. Gdyby tablica była pusta, moje rozwiązanie API podniosłoby ją, ale gdyby tablica zawierała element, metoda kontrolera nie byłaby w stanie modelować wiązania JSON. Dzięki za to. Wydaje mi się, że PostAsJsonAsync bardziej niezawodnie konwertuje złożony obiekt C # na JSON.
Franklin Tarter

Czy jest do tego pakiet nuget? Nienawidzę go, gdy przenoszę projekt na nową maszynę, a tego odniesienia zawsze brakuje.
Zapnologica


51

Jeśli używasz 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");
}

Przykład:

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

nie jest to specyficzne dla rdzenia asp.net, jest w zasadzie ogólne nawet do 4.5.6
danatcofo

JsonConvert.SerializeObjectproblemy z użyciem DateTimes ISO 8601 Rodzaj: lokalny lub UTC ... hackered.co.uk/articles/…
Kiquenet

21

Nie mam wystarczającej reputacji, aby dodać komentarz do odpowiedzi pomber, więc zamieszczam inną odpowiedź. Stosując podejście pomber, ciągle otrzymywałem odpowiedź „400 Bad Request” z interfejsu API, do którego wysyłałem moje zapytanie JSON (Visual Studio 2017, .NET 4.6.2). Ostatecznie problem został przypisany do nieprawidłowego nagłówka „Content-Type” wygenerowanego przez StringContent () (patrz https://github.com/dotnet/corefx/issues/7864 ).

tl; dr

Użyj odpowiedzi pomber z dodatkową linią, aby poprawnie ustawić nagłówek na żądanie:

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

Dziękuję, mrowiska. var content = new StringContent (jsonObject.ToString (), Encoding.UTF8, „application / json”) to za mało. Potrzebuje content.Headers.ContentType = new MediaTypeHeaderValue („application / json”); Dziękuję za uratowanie mi zdrowia psychicznego.
Gail Foad

1
To działało świetnie. Czy jest jakiś powód, dla którego „application / json” należy ustawić dwa razy, jeden w konstruktorze i raz za pośrednictwem właściwości? Czy to błąd?
Festus Martingale,

@FestusMartingale: dobre pytanie! Z mojego czytania emisji github (połączonego odpowiedź) przejścia "application/json"w StringContentkonstruktorze prawdopodobnie nie jest wymagane, ponieważ jest jawnie ustawiona na wynikającym z content.Headers.ContentTypewłasności. Nie przetestowałem tego jednak w kodzie.
mrówki

Wygląda na to, że serwer nie obsługuje pełnego typu ciągu znaków. Gdy używasz konstruktora bez nadpisywania ContentType, ustawia on wartość na application/json; charset=utf-8.
Bertm13

2

kod nad nim w 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)

Mam nadzieję, że to pomoże

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.