Recevoir des données JSON à partir d'une requête HTTP

91

J'ai une requête Web qui fonctionne correctement, mais elle renvoie simplement le statut OK, mais j'ai besoin de l'objet que je demande. Je ne sais pas comment obtenir la valeur json que je demande. Je suis nouveau dans l'utilisation de l'objet HttpClient, y a-t-il une propriété qui me manque? J'ai vraiment besoin de l'objet de retour. Merci pour toute aide

Passer l'appel - s'exécute correctement renvoie le statut 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;

La méthode api get

//Cut out alot of code but you get the idea
public string Get()
{
    return JsonConvert.SerializeObject(returnedPhoto);
}
user516883
la source
Demandez-vous comment obtenir le contenu de la réponse lors de l'utilisation de la classe HttpClient .NET 4.5?
Panagiotis Kanavos

Réponses:

162

Si vous faites référence à System.Net.HttpClient dans .NET 4.5, vous pouvez obtenir le contenu renvoyé par GetAsync à l'aide de la propriété HttpResponseMessage.Content en tant qu'objet dérivé de HttpContent. Vous pouvez ensuite lire le contenu dans une chaîne à l'aide de la méthode HttpContent.ReadAsStringAsync ou sous forme de flux à l'aide de la méthode ReadAsStreamAsync .

La documentation de la classe HttpClient comprend cet exemple:

  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
  response.EnsureSuccessStatusCode();
  string responseBody = await response.Content.ReadAsStringAsync();
Panagiotis Kanavos
la source
3
Je n'ai pas testé cela, mais la documentation d'EnsureSuccessStatusCode indique "Si le contenu n'est pas nul, cette méthode appellera également Dispose pour libérer les ressources gérées et non gérées." vous souhaiterez peut-être lire le contenu en premier. msdn.microsoft.com/en-us/library/…
Ryan Williams
4
Aucune raison à cela. Comme en témoigne Reflector, EnsureSuccessStatusCode supprimera UNIQUEMENT si le code d'état échoue, juste avant de lever une exception. Encore un autre cas où le texte de la documentation est légèrement déroutant.
Panagiotis Kanavos
1
Pourquoi pas juste client.GetStringAsync(...)? N'était-ce pas là en 2012. Ils lanceraient tous les deux une exception si la réponse n'était pas 200correcte?
Simon_Weaver
1
@Simon_Weaver parce que ce n'était pas la question - l'OP a demandé comment lire la chaîne de la réponse. Il y a des différences. Vous ne pouvez pas inspecter la réponse, GetStringAsyncce qui signifie que vous ne savez pas quel était le message de réponse. Vous ne voudrez probablement pas lancer si une réponse 3xx est renvoyée. Vous souhaiterez probablement réessayer sans lancer si une erreur de limitation est renvoyée.
Panagiotis Kanavos
1
@Simon_Weaver, il existe de nombreuses façons de passer cet appel - pourquoi pas GetAsync<T>? Ou GetStreamAsync et passer le flux à Json.NET, en évitant la chaîne temporaire? Encore une fois, il peut être préférable d'utiliser d' GetAsyncabord puis d'accéder à l'objet de contenu
Panagiotis Kanavos
40

En nous basant sur la réponse de @Panagiotis Kanavos , voici une méthode de travail comme exemple qui retournera également la réponse sous forme d'objet au lieu d'une chaîne:

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

Gardez à l'esprit qu'il ne s'agit que d'un exemple et que vous aimeriez probablement l'utiliser HttpClientcomme instance partagée au lieu de l'utiliser dans une clause d'utilisation.

Wouter Vanherck
la source
Attention, httpclient ne dispose pas comme ça avec la déclaration d'utilisation
rogue39nin
Puisque wait revient immédiatement, il est possible que cela if (response != null)soit exécuté avant la fin de l'appel de publication?
Nishant
7

Je pense que le moyen le plus court est:

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.
la source
7
Je pensais juste ajouter que ReadAsAsync est une méthode d'extension. vous devrez utiliser System.Net.Http.Formatting pour .net 4+ et Microsoft.AspNet.WebApi.Client pour .net core. pour que cela fonctionne.
Squably
0

Ce que je fais normalement, comme pour répondre à une:

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

Où 'model' est votre classe de modèle C #.

James Heffer
la source
0

Cela fonctionne bien pour moi de la manière suivante -

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
la source