2016-04-14 4 views
22

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

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. Пары данных являются объект, как это:

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

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

+0

Если я правильно понял ваш вопрос, вы хотите, чтобы отправить содержимое JSON вместо формы кодируются содержания (и по расширению вы хотите, чтобы ваш анонимный тип был сериализован как JSON в этот контент)? – CodingGorilla

+0

@CodingGorilla yes - анонимный тип. – IlDrugo

ответ

39

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

общественной задачи 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 свойство, как вы делаете здесь может иметь некоторые bad side effects таких как мертвая блокировка, поэтому вы хотите быть осторожными с этим.

+0

Хорошо, это очень ясно. Спасибо за этот ответ. Просто вопрос: когда выполняется 'POST, PUT, DELETE', обычно API возвращает' TRUE', я объявлял метод как 'string', но когда я это делаю:' return result; 'Я получаю:' Can not Преобразовать HttpResponseMessage в строку', следует ли мне изменить объявление метода? Мне нужен строковый ответ, потому что мне придется десериализовать его в другом методе класса. – IlDrugo

+1

Если вам нужно десериализовать тело ответа, то верните строку так, как вы в своем вопросе (используя 'result.Content.ReadAsStringAsync()'), вероятно, просто отлично. В зависимости от структуры вашего приложения может быть лучше вернуть объект «Content» напрямую, если вам нужно проверить заголовки, чтобы определить, что такое тип коннеста (например, XML или JSON). Но если вы ** знаете **, он всегда будет возвращать JSON (или какой-то другой формат), а просто возвращает тело ответа, поскольку строка должна быть в порядке. – CodingGorilla

+0

Получил, спасибо :) – IlDrugo

6

Вам необходимо передать свои данные в тело запроса как необработанную строку, а не FormUrlEncodedContent. Один из способов сделать это, чтобы сериализовать в строку JSON:

var json = JsonConvert.SerializeObject(data); 

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

var stringContent = new HttpStringContent(json, 
         UnicodeEncoding.Utf8, 
         "application/json"); 

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

Обратите внимание, что 'HttpStringContent' - это класс времени выполнения Windows, который не всегда доступен. См. Раздел «Требования» [здесь] (https://msdn.microsoft.com/en-us/library/windows/apps/windows.web.http.httpstringcontent.aspx). – CodingGorilla

+0

Да, это портативная библиотека классов. – IlDrugo

4

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

Тогда вы можете просто сделать это, и это будет сериализовать объект JSON и установить Content-Type заголовок 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); 
Смежные вопросы