Розміщення JsonObject з HttpClient від веб-API


289

Я намагаюсь відмітити JsonObjectвикористання HttpClientчерез Web API. Я не зовсім впевнений, як це зробити, і не можу знайти багато на шляху зразкового коду.

Ось що я маю досі:

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

Я думаю, що мені потрібно подати свою JsonObjectроль, StreamContentале я зациклювався на цьому кроці.

Відповіді:


441

З новою версією пакету HttpClientта без WebApiнього було б:

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

Або якщо ви хочете async:

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

3
Цей перевантажений конструктор StringContent зробив для мене трюк.
Капітан Кенпачі

23
Подумайте двічі, перш ніж викликати Результат методом Async, хоча blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Ручіра,

2
Для всіх, хто спокусився кинути це usingсхожим чином, я був: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

Я поклав usingнавколо StringContentстворення, хоча.
bcr

Використовуючи цю відповідь, я продовжував отримувати відповідь "400 поганих запитів" від API, на який я відправив запит JSON (Visual Studio 2017, .NET 4.6.2). Окрім того, var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json")мені довелося встановити content.Headers.ContentType = new MediaTypeHeaderValue("application/json");. Детальну інформацію див. У відповіді нижче.
мурахи

161

Найпростіший спосіб - використовувати StringContent, з JSON-представленням вашого JSON-об'єкта.

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

14
Візьміть до відома тип вмісту. Я покинув це і змусив налагоджувати набагато довше, ніж хотів би.
Zapnologica

Чи не варто вам розпоряджатися екземпляром StringContent?
Філ Хасельден

63

Залежно від версії .NET ви також можете використовувати HttpClientExtensions.PostAsJsonAsyncметод.

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


4
Зараз знайдено в Microsoft.AspNet.Client.WebApi nuget
jle

2
Я щойно встановив його від Microsoft.AspNet.WebApi.Client
Адріан Давель

Це вирішило мою проблему. Я возився навколо (довгий), передаючи клас C #, який містив деякі властивості, що містилися у списках за допомогою client.PostAsync, client.SendAsync .. Я отримував дуже неоднозначні результати. Якщо масив був порожнім, моє рішення API взяло б його, але якщо в масиві був елемент, метод контролера не зміг моделювати прив'язку JSON. Дякую за це .. Мені здається, що PostAsJsonAsync надійніше перетворює складний об'єкт C # в JSON.
Франклін Тартер

Чи є для цього пакет нута? Я ненавиджу це, коли я переношу проект на нову машину, і ця посилання завжди відсутня.
Zapnologica


51

Якщо використовується 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");
}

Приклад:

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

це не основна особливість asp.net, а фактично загальна - аж до
4,5,6

JsonConvert.SerializeObjectпроблеми, що використовують DateTimes ISO 8601 Вид: Місцевий або UTC ... hackered.co.uk/articles/…
Кікенет

21

У мене недостатньо репутації, щоб додати коментар до відповіді з помберу, тому я публікую ще одну відповідь. Використовуючи підхід помберу, я продовжував отримувати відповідь "400 поганого запиту" від API, на який я розміщував запит JSON (Visual Studio 2017, .NET 4.6.2). Врешті-решт проблема була простежена у тому, що заголовок "Content-Type", створений StringContent (), є неправильним (див. Https://github.com/dotnet/corefx/isissue/7864 ).

тл; д-р

Використовуйте відповідь помберу з додатковим рядком, щоб правильно встановити заголовок на запит:

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

Дякую, мурашки змісту var = новий StringContent (jsonObject.ToString (), Encoding.UTF8, "application / json") було недостатньо. Він потребує content.Headers.ContentType = новий MediaTypeHeaderValue ("application / json"); Дякую, що врятували мій розум.
Гейл Фоад

1
Це спрацювало чудово. Будь-яка причина, чому "application / json" потрібно встановити двічі, один у конструкторі та один раз через властивість? Це помилка?
Festus

@FestusMartingale: гарне запитання! З мого читання питання github (пов'язаного у відповіді) проходження "application/json"в StringContentконструкторі, ймовірно, не потрібно, оскільки воно чітко встановлено на отриманому content.Headers.ContentTypeвластивості. Однак я не перевіряв це в коді.
мурашки

Схоже, сервер не підтримує повний рядок типу вмісту. Коли ви використовуєте конструктор, не змінюючи ContentType, він встановлює значення як application/json; charset=utf-8.
Bertm13

2

код над ним у 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)

Сподіваюся, що це допоможе

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.