Получение данных 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);
}

Вы спрашиваете, как получить содержимое ответа при использовании класса .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


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;
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.