Ricezione di dati JSON indietro dalla richiesta HTTP


97

Ho una richiesta web che funziona correttamente, ma restituisce solo lo stato OK, ma ho bisogno che l'oggetto che chiedo venga restituito. Non sono sicuro di come ottenere il valore json che sto richiedendo. Sono nuovo nell'uso dell'oggetto HttpClient, c'è una proprietà che mi sto perdendo? Ho davvero bisogno dell'oggetto restituito. Grazie per qualsiasi aiuto

Effettuare la chiamata - funziona correttamente restituisce lo stato 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;

Il metodo api get

//Cut out alot of code but you get the idea
public string Get()
{
    return JsonConvert.SerializeObject(returnedPhoto);
}

Stai chiedendo come ottenere il contenuto della risposta quando si utilizza la classe .NET 4.5 HttpClient?
Panagiotis Kanavos

Risposte:


168

Se si fa riferimento a System.Net.HttpClient in .NET 4.5, è possibile ottenere il contenuto restituito da GetAsync utilizzando la proprietà HttpResponseMessage.Content come oggetto derivato da HttpContent . È quindi possibile leggere il contenuto in una stringa utilizzando il metodo HttpContent.ReadAsStringAsync o come flusso utilizzando il metodo ReadAsStreamAsync .

La documentazione della classe HttpClient include questo esempio:

  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
  response.EnsureSuccessStatusCode();
  string responseBody = await response.Content.ReadAsStringAsync();

3
Non l'ho testato ma la documentazione di GuaranteSuccessStatusCode dice "Se il contenuto non è nullo, questo metodo chiamerà anche Dispose per liberare risorse gestite e non gestite." quindi potresti voler leggere prima il contenuto. msdn.microsoft.com/en-us/library/…
Ryan Williams,

4
Nessun motivo per questo. Come evidenziato da Reflector, GuaranteSuccessStatusCode eliminerà SOLO se il codice di stato non ha esito positivo, subito prima di lanciare un'eccezione. Ancora un altro caso in cui il testo della documentazione è leggermente confuso.
Panagiotis Kanavos

1
Perché non solo client.GetStringAsync(...)? Non c'era nel 2012. Entrambi avrebbero lanciato un'eccezione se la risposta non fosse stata 200giusta?
Simon_Weaver

1
@ Simon_Weaver perché non era quella la domanda: l'OP ha chiesto come leggere la stringa dalla risposta. Ci sono differenze. Non puoi esaminare la risposta con il GetStringAsyncche significa che non sai quale fosse il messaggio di risposta. Probabilmente non vuoi lanciare se viene restituita una risposta 3xx. Probabilmente vorrai riprovare senza lanciare se viene restituito un errore di limitazione.
Panagiotis Kanavos

1
@ Simon_Weaver ci sono molti modi per fare quella chiamata - perché no GetAsync<T>? Oppure GetStreamAsync e passare il flusso a Json.NET, evitando la stringa temporanea? Anche in questo caso, potrebbe essere preferibile utilizzare GetAsyncprima quindi accedere all'oggetto contenuto
Panagiotis Kanavos

43

Basandosi sulla risposta di @Panagiotis Kanavos , ecco un metodo di lavoro come esempio che restituirà anche la risposta come oggetto anziché come stringa:

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

Tieni presente che questo è solo un esempio e che probabilmente vorresti usare HttpClientcome istanza condivisa invece di usarlo in una clausola using.


Fai attenzione che httpclient non disponga in questo modo con la dichiarazione di utilizzo
rogue39nin

Dato che await ritorna immediatamente, è possibile che if (response != null)venga eseguito prima che la chiamata successiva sia stata completata?
Nishant

Non vedo alcuna differenza, anche se hai detto "restituisci la risposta come oggetto invece che come stringa.", In tal caso, perché stai eseguendo un passaggio manuale aggiuntivo utilizzando JsonConvert.DeserializedObject (), ovvero sei convertire la stringa in oggetto sul client dopo che è stata ricevuta (come stringa).
Joedotnon


8

Penso che la via più breve sia:

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
Ho pensato solo di aggiungere che ReadAsAsync è un metodo di estensione. sarà necessario utilizzare System.Net.Http.Formatting per .net 4+ e Microsoft.AspNet.WebApi.Client per .net core. per farlo funzionare.
Squibly

0

Quello che faccio normalmente, simile a rispondere a uno:

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

Dove "modello" è la classe del modello C #.


0

Funziona bene per me nel modo seguente:

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;
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.