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.

znak
źródło

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);
pomber
źródło
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"));
carlosfigueira
źródło
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

użytkownik3285954
źródło
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
Szukasz tego czy czegoś innego? nuget.org/packages/Microsoft.AspNet.WebApi.Client
user3285954
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())
Matthew Steven Monkan
źródło
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;
mrowiska
źródło
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

Stefano Ronchese
źródło