Получение данных JSON обратно из HTTP-запроса

97

У меня есть веб-запрос, который работает правильно, но он просто возвращает статус ОК, но мне нужен объект, который я прошу вернуть. Я не уверен, как получить запрашиваемое значение json. Я новичок в использовании объекта HttpClient, есть ли свойство, которое мне не хватает? Мне действительно нужен возвращаемый объект. Спасибо за любую помощь

Совершение звонка - работает нормально, возвращает статус ОК.

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept
  .Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMsg = client.GetAsync(string.Format("http://localhost:5057/api/Photo")).Result;

Метод api get

//Cut out alot of code but you get the idea
public string Get()
{
    return JsonConvert.SerializeObject(returnedPhoto);
}
user516883
источник
Вы спрашиваете, как получить содержимое ответа при использовании класса .NET 4.5 HttpClient?
Панайотис Канавос

Ответы:

168

Если вы имеете в виду System.Net.HttpClient в .NET 4.5, вы можете получить контент, возвращаемый GetAsync, используя свойство HttpResponseMessage.Content как объект, производный от HttpContent. Затем вы можете прочитать содержимое в строке с помощью метода HttpContent.ReadAsStringAsync или в виде потока с помощью метода ReadAsStreamAsync .

HttpClient документация класс включает этот пример:

  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
  response.EnsureSuccessStatusCode();
  string responseBody = await response.Content.ReadAsStringAsync();
Панайотис Канавос
источник
3
Не тестировал это, но в документации EnsureSuccessStatusCode говорится: «Если Content не равно нулю, этот метод также вызовет Dispose для освобождения управляемых и неуправляемых ресурсов». так что вы можете сначала прочитать содержание. msdn.microsoft.com/en-us/library/…
Райан Уильямс,
4
Нет причин для этого. Как свидетельствует Reflector, EnsureSuccessStatusCode удалит ТОЛЬКО, если код состояния неуспешен, прямо перед генерацией исключения. Еще один случай, когда текст документации немного сбивает с толку.
Панайотис Канавос
1
Почему не просто так client.GetStringAsync(...)? Разве этого не было в 2012 году. Они оба выбросили бы исключение, если бы ответ был 200неправильным?
Simon_Weaver
1
@Simon_Weaver, потому что вопрос не в этом - OP спросил, как читать строку из ответа. Там является различие. Вы не можете проверить ответ, GetStringAsyncчто означает, что вы не знаете, что было ответным сообщением. Вы, вероятно , не захотите бросать, если возвращается ответ 3xx. Вы, вероятно, захотите повторить попытку, не выбрасывая, если возвращается ошибка регулирования.
Панайотис Канавос
1
@Simon_Weaver, есть много способов сделать этот звонок - почему бы и нет GetAsync<T>? Или GetStreamAsync и передать поток в Json.NET, избегая временной строки? Опять же, может быть предпочтительнее GetAsyncсначала использовать, а затем получить доступ к объекту содержимого
Панайотис Канавос
43

Основываясь на ответе @Panagiotis Kanavos , вот рабочий метод в качестве примера, который также вернет ответ в виде объекта, а не строки:

using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json; // Nuget Package

public static async Task<object> PostCallAPI(string url, object jsonObject)
{
    try
    {
        using (HttpClient client = new HttpClient())
        {
            var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
            var response = await client.PostAsync(url, content);
            if (response != null)
            {
                var jsonString = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<object>(jsonString);
            }
        }
    }
    catch (Exception ex)
    {
        myCustomLogger.LogException(ex);
    }
    return null;
}

Имейте в виду, что это всего лишь пример, и вы, вероятно, хотели бы использовать его HttpClientв качестве общего экземпляра, а не использовать его в предложении using.

Воутер Ванхерк
источник
Будьте осторожны, httpclient не избавляется от подобного со
статусом
Поскольку await возвращается немедленно, возможно ли, что он if (response != null)будет выполнен до завершения вызова post?
Nishant
Я не вижу разницы, даже если вы сказали «вернуть ответ как объект, а не строку». Если это так, то почему вы выполняете дополнительный ручной шаг с помощью JsonConvert.DeserializedObject (), т.е. вы преобразование строки в объект на клиенте после ее получения (в виде строки).
joedotnot
11

Установите этот пакет nuget от Microsoft System.Net.Http.Json. Он содержит методы расширения.

Затем добавьте using System.Net.Http.Json

Теперь вы сможете увидеть эти методы:

введите описание изображения здесь

Итак, теперь вы можете сделать это:

await httpClient.GetFromJsonAsync<IList<WeatherForecast>>("weatherforecast");

Источник: https://www.stevejgordon.co.uk/sending-and-receiving-json-using-httpclient-with-system-net-http-json

Alansiqueira27
источник
8

Думаю, самый короткий путь:

var client = new HttpClient();
string reqUrl = $"http://myhost.mydomain.com/api/products/{ProdId}";
var prodResp = await client.GetAsync(reqUrl);
if (!prodResp.IsSuccessStatusCode){
    FailRequirement();
}
var prods = await prodResp.Content.ReadAsAsync<Products>();
Грег З.
источник
8
Просто подумал, что id добавить, что ReadAsAsync - это метод расширения. вам нужно будет использовать System.Net.Http.Formatting для .net 4+ и Microsoft.AspNet.WebApi.Client для ядра .net. чтобы это работало.
Squible
0

То, что я обычно делаю, похоже на ответ:

var response = await httpClient.GetAsync(completeURL); // http://192.168.0.1:915/api/Controller/Object

if (response.IsSuccessStatusCode == true)
    {
        string res = await response.Content.ReadAsStringAsync();
        var content = Json.Deserialize<Model>(res);

// do whatever you need with the JSON which is in 'content'
// ex: int id = content.Id;

        Navigate();
        return true;
    }
    else
    {
        await JSRuntime.Current.InvokeAsync<string>("alert", "Warning, the credentials you have entered are incorrect.");
        return false;
    }

Где «модель» - это ваш класс модели C #.

Джеймс Хеффер
источник
0

У меня он отлично работает следующим образом -

public async Task<object> TestMethod(TestModel model)
    {
        try
        {
            var apicallObject = new
            {
                Id= model.Id,
                name= model.Name
            };

            if (apicallObject != null)
            {
                var bodyContent = JsonConvert.SerializeObject(apicallObject);
                using (HttpClient client = new HttpClient())
                {
                    var content = new StringContent(bodyContent.ToString(), Encoding.UTF8, "application/json");
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    client.DefaultRequestHeaders.Add("access-token", _token); // _token = access token
                    var response = await client.PostAsync(_url, content); // _url =api endpoint url
                    if (response != null)
                    {
                        var jsonString = await response.Content.ReadAsStringAsync();

                        try
                        {
                            var result = JsonConvert.DeserializeObject<TestModel2>(jsonString); // TestModel2 = deserialize object
                        }
                        catch (Exception e){
                            //msg
                            throw e;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return null;
    }
Bulbul bd
источник