Odbieranie danych JSON z powrotem z żądania HTTP

90

Mam żądanie sieciowe, które działa poprawnie, ale po prostu zwraca stan OK, ale potrzebuję obiektu, o który proszę, aby zwrócił. Nie jestem pewien, jak uzyskać żądaną wartość json. Jestem nowy w używaniu obiektu HttpClient, czy brakuje mi właściwości? Naprawdę potrzebuję zwracanego obiektu. Dzięki za wszelką pomoc

Wykonywanie połączenia - działa poprawnie, zwraca stan OK.

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

Metoda API GET

//Cut out alot of code but you get the idea
public string Get()
{
    return JsonConvert.SerializeObject(returnedPhoto);
}
user516883
źródło
Czy pytasz, jak uzyskać treść odpowiedzi, korzystając z klasy HttpClient .NET 4.5?
Panagiotis Kanavos

Odpowiedzi:

161

Jeśli odwołujesz się do System.Net.HttpClient w .NET 4.5, możesz pobrać zawartość zwróconą przez GetAsync przy użyciu właściwości HttpResponseMessage.Content jako obiektu pochodnego HttpContent . Następnie można odczytać zawartość do ciągu przy użyciu metody HttpContent.ReadAsStringAsync lub jako strumień przy użyciu metody ReadAsStreamAsync .

Dokumentacja klasy HttpClient zawiera ten przykład:

  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
  response.EnsureSuccessStatusCode();
  string responseBody = await response.Content.ReadAsStringAsync();
Panagiotis Kanavos
źródło
3
Nie testowałem tego, ale dokumentacja GuaranteSuccessStatusCode mówi: „Jeśli zawartość nie jest null, ta metoda wywoła również Dispose, aby zwolnić zarządzane i niezarządzane zasoby”. więc możesz chcieć najpierw przeczytać treść. msdn.microsoft.com/en-us/library/…
Ryan Williams
4
Nie ma powodu. Jak widać na przykładzie Reflector, RememberSuccessStatusCode usunie TYLKO, jeśli kod stanu nie powiedzie się, tuż przed zgłoszeniem wyjątku. Kolejny przypadek, w którym tekst dokumentacji jest nieco zagmatwany.
Panagiotis Kanavos
1
Dlaczego nie po prostu client.GetStringAsync(...)? Czy nie było tego w 2012 roku. Obaj rzuciliby wyjątek, gdyby odpowiedź nie była 200właściwa?
Simon_Weaver
1
@Simon_Weaver, bo to nie było pytanie - OP zapytał, jak odczytać ciąg z odpowiedzi. Tam różnice. Nie możesz sprawdzić odpowiedzi, GetStringAsyncco oznacza, że ​​nie wiesz, jaka była wiadomość z odpowiedzią. Prawdopodobnie nie chcesz rzucać, jeśli zostanie zwrócona odpowiedź 3xx. Prawdopodobnie chcesz spróbować ponownie bez zgłaszania, jeśli zostanie zwrócony błąd ograniczania przepustowości.
Panagiotis Kanavos,
1
@Simon_Weaver Jest wiele sposobów wykonania tego połączenia - czemu nie GetAsync<T>? Lub GetStreamAsync i przekaż strumień do Json.NET, unikając tymczasowego ciągu? Ponownie, może być lepiej GetAsyncnajpierw użyć, a następnie uzyskać dostęp do obiektu treści
Panagiotis Kanavos,
39

Opierając się na odpowiedzi @Panagiotis Kanavos , oto działająca metoda jako przykład, która również zwróci odpowiedź jako obiekt zamiast ciągu:

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;
}

Pamiętaj, że to jest tylko przykład i prawdopodobnie chciałbyś użyć go HttpClientjako współdzielonej instancji, zamiast używać jej w klauzuli using.

Wouter Vanherck
źródło
Bądź ostrożny, httpclient nie pozbywa się tego z instrukcją using
rogue39nin
Ponieważ await zwraca natychmiast, możliwe jest, że if (response != null)jest wykonywany przed zakończeniem wywołania końcowego?
Nishant
7

Myślę, że najkrótsza droga to:

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>();
Greg Z.
źródło
7
Pomyślałem, że id dodać, że ReadAsAsync jest metodą rozszerzającą. będziesz musiał użyć System.Net.Http.Formatting dla .net 4+ i Microsoft.AspNet.WebApi.Client dla .net core. żeby to działało.
Kwadratowy
0

To, co zwykle robię, podobne do odpowiedzi na jedno:

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;
    }

Gdzie „model” to klasa modelu w języku C #.

James Heffer
źródło
0

Dla mnie działa dobrze w następujący sposób -

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
źródło