POSTing JsonObject с помощью HttpClient из веб-API


289

Я пытаюсь опубликовать JsonObjectиспользование HttpClientиз веб-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но я зацикливаюсь на этом шаге.

Ответы:


443

С новой версией 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
Подумайте дважды, прежде чем вызывать Result для асинхронного метода, хотя blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Ruchira,

2
Для любого, кто испытывал желание бросить это usingкак я: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

Я положил usingвокруг StringContentсоздания хотя.
BCR

1
Используя этот ответ, я продолжал получать ответ «400 Bad Request» от 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

2
Я только что установил его из Microsoft.AspNet.WebApi.Client
Adriaan Davel

Это решило мою проблему. Я долго (долго) возился, передавая класс C #, который содержал некоторые свойства, которые были списками с использованием client.PostAsync, client.SendAsync .. Я получал очень смешанные результаты. Если бы массив был пустым, мое API-решение подобрало бы его, но если бы в массиве был элемент, метод контроллера не смог бы связать модель JSON. Спасибо за это .. Мне кажется, что PostAsJsonAsync более надежно преобразует сложный объект C # в JSON.
Франклин Тартер

Для этого есть пакет Nuget? Я ненавижу, когда я переношу проект на новую машину, и эта ссылка всегда отсутствует.
Zapnologica

Ищете это или что-то еще? nuget.org/packages/Microsoft.AspNet.WebApi.Client
user3285954

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
danatcofo

JsonConvert.SerializeObjectпроблемы с использованием DateTimes ISO 8601 Вид: локальный или UTC ... hackered.co.uk/articles/…
Kiquenet

21

У меня недостаточно репутации, чтобы добавить комментарий к ответу от pomber, поэтому я публикую другой ответ. Используя подход pomber, я продолжал получать ответ «400 Bad Request» от API, к которому я отправлял свой запрос JSON (Visual Studio 2017, .NET 4.6.2). В конечном итоге проблема была связана с неправильным заголовком «Content-Type», созданным StringContent () (см. Https://github.com/dotnet/corefx/issues/7864 ).

ТЛ; др

Используйте ответ pomber с дополнительной строкой, чтобы правильно установить заголовок запроса:

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 content = new StringContent (jsonObject.ToString (), Encoding.UTF8, "application / json") было недостаточно. Для этого требуется content.Headers.ContentType = new MediaTypeHeaderValue ("application / json"); Спасибо за спасение моего здравомыслия.
Гейл Фоад

1
Это сработало отлично. Любая причина, почему "application / json" должен быть установлен дважды, один в конструкторе и один раз через свойство? Это ошибка?
Фест Мартингейл

@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.