Подтвердить что ты не робот

Как передать объект HttpClient.PostAsync и сериализовать как тело JSON?

Я использую System.Net.Http, я нашел несколько примеров в Интернете. Мне удалось создать этот код для запроса POST:

public static string POST(string resource, string token)
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(baseUri);
        client.DefaultRequestHeaders.Add("token", token);

        var content = new FormUrlEncodedContent(new[]
        {
             new KeyValuePair<string, string>("", "")
        });

        var result = client.PostAsync("", content).Result;
        string resultContent = result.Content.ReadAsStringAsync().Result;
        return resultContent;
    }
 }

все работает нормально. Но предположим, что я хочу передать третий параметр методу POST, параметр под названием data. Параметр data представляет собой такой объект:

object data = new
{
    name = "Foo",
    category = "article"
};

как я могу это сделать без создания KeyValuePair? Мой php RestAPI ждет ввода json, поэтому FormUrlEncodedContent должен правильно отправить raw json. Но как я могу сделать это с помощью Microsoft.Net.Http? Спасибо.

4b9b3361

Ответ 1

Прямой ответ на ваш вопрос: Нет. Подпись для метода PostAsync выглядит следующим образом:

public Task PostAsync (Uri requestUri, контент HttpContent)

Итак, хотя вы можете передать object в PostAsync, он должен иметь тип HttpContent, а ваш анонимный тип не соответствует этим критериям.

Однако есть способы выполнить то, что вы хотите выполнить. Во-первых, вам нужно будет сериализовать ваш анонимный тип в JSON, наиболее распространенным инструментом для этого является Json.NET. И код для этого довольно тривиален:

var myContent = JsonConvert.SerializeObject(data);

Затем вам нужно будет создать объект содержимого для отправки этих данных, я буду использовать объект ByteArrayContent, но вы могли бы использовать или создать другой тип, если хотите.

var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);

Затем вы хотите установить тип содержимого, чтобы API знал, что это JSON.

byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

Затем вы можете отправить свой запрос, очень похожий на ваш предыдущий пример, с содержимым формы:

var result = client.PostAsync("", byteContent).Result

На стороне примечания, вызов свойства .Result, как вы здесь, может иметь некоторые плохие побочные эффекты, такие как мертвая блокировка, поэтому вы хотите быть осторожно с этим.

Ответ 2

Вам нужно передать ваши данные в теле запроса в виде необработанной строки, а не FormUrlEncodedContent. Один из способов сделать это - сериализовать его в строку JSON:

var json = JsonConvert.SerializeObject(data);

Теперь все, что вам нужно сделать, это передать строку методу post.

var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json");

var client = new HttpClient();
var response = await client.PostAsync(uri, stringContent);

Ответ 3

Простым решением является использование Microsoft ASP.NET Web API 2.2 Client от NuGet.

Затем вы можете просто сделать это, и он будет сериализовать объект в JSON и установить заголовок Content-Type в application/json; charset=utf-8 application/json; charset=utf-8:

var data = new
{
    name = "Foo",
    category = "article"
};

var client = new HttpClient();
client.BaseAddress = new Uri(baseUri);
client.DefaultRequestHeaders.Add("token", token);
var response = await client.PostAsJsonAsync("", data);

Ответ 4

Там теперь более простой способ с .NET Standard или .NET Core:

var client = new HttpClient();
var response = await client.PostAsync(uri, myRequestObject, new JsonMediaTypeFormatter());

ПРИМЕЧАНИЕ. Чтобы использовать класс JsonMediaTypeFormatter, вам необходимо установить пакет Microsoft.AspNet.WebApi.Client NuGet, который можно установить напрямую или через другой, такой как Microsoft.AspNetCore.App.

Используя эту подпись HttpClient.PostAsync, вы можете передать любой объект, и JsonMediaTypeFormatter автоматически позаботится о сериализации и т.д.

С ответом вы можете использовать HttpContent.ReadAsAsync<T> для десериализации содержимого ответа к типу, который вы ожидаете:

var responseObject = await response.Content.ReadAsAsync<MyResponseType>();