web-dev-qa-db-fra.com

Comment lire les réponses de l'API Web avec HttpClient en C #

Je suis relativement nouveau sur webapi et j'ai développé une petite webapi qui a quelques actions et renvoie ma classe personnalisée appelée Response.

La classe Response

public class Response
{
    bool IsSuccess=false;
    string Message;
    object ResponseData;

    public Response(bool status, string message, object data)
    {
        IsSuccess = status;
        Message = message;
        ResponseData = data;
    }
}

Ma webapi avec actions

[RoutePrefix("api/customer")]
public class CustomerController : ApiController
{
    static readonly ICustomerRepository repository = new CustomerRepository();

    [HttpGet, Route("GetAll")]
    public Response GetAllCustomers()
    {
        return new Response(true, "SUCCESS", repository.GetAll());
    }

    [HttpGet, Route("GetByID/{customerID}")]
    public Response GetCustomer(string customerID)
    {
        Customer customer = repository.Get(customerID);
        if (customer == null)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }
        return new Response(true, "SUCCESS", customer);
        //return Request.CreateResponse(HttpStatusCode.OK, response);
    }

    [HttpGet, Route("GetByCountryName/{country}")]
    public IEnumerable<Customer> GetCustomersByCountry(string country)
    {
        return repository.GetAll().Where(
            c => string.Equals(c.Country, country, StringComparison.OrdinalIgnoreCase));
    }
}

Maintenant, où je suis bloqué, c'est que je ne sais pas lire les données de réponse renvoyées par les actions webapi et extraire json de ma classe de réponse. Après avoir obtenu json, comment pourrais-je deserialize ce json à la classe client.

C'est ainsi que j'appelle ma fonction webapi:

private void btnLoad_Click(object sender, EventArgs e)
{
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:8010/");
    // Add an Accept header for JSON format.  
    //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    // List all Names.  
    HttpResponseMessage response = client.GetAsync("api/customer/GetAll").Result;  // Blocking call!  
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine("Request Message Information:- \n\n" + response.RequestMessage + "\n");
        Console.WriteLine("Response Message Header \n\n" + response.Content.Headers + "\n");
    }
    else
    {
        Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
    }
    Console.ReadLine();   
}

Aidez-moi à trier mon code

1) Comment obtenir la classe de réponse renvoyée par la webapi côté client

2) Comment extraire json de la classe de réponse

3) Comment désérialiser le json vers la classe client côté client

Merci

ÉDITER

J'utilise ce code mais j'obtiens toujours une erreur.

    var baseAddress = "http://localhost:8010/api/customer/GetAll";
    using (var client = new HttpClient())
    {
        using (var response =  client.GetAsync(baseAddress).Result)
        {
            if (response.IsSuccessStatusCode)
            {
                var customerJsonString = await response.Content.ReadAsStringAsync();
                var cust = JsonConvert.DeserializeObject<Response>(customerJsonString);
            }
            else
            {
                Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
            }
        }
    }

T le message d'erreur est:

Une exception de type "Newtonsoft.Json.JsonSerializationException" s'est produite dans Newtonsoft.Json.dll mais n'a pas été gérée dans le code utilisateur

Informations supplémentaires: Impossible de désérialiser l'objet JSON actuel (par exemple {"nom": "valeur"}) dans le type 'WebAPIClient.Response []' car le type nécessite un tableau JSON (par exemple [1,2,3]) pour désérialiser correctement .

Pourquoi la réponse provoque-t-elle cette erreur?

7
Monojit Sarkar

Sur le client, incluez une lecture du contenu:

    HttpResponseMessage response = client.GetAsync("api/customer/GetAll").Result;  // Blocking call!  
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine("Request Message Information:- \n\n" + response.RequestMessage + "\n");
        Console.WriteLine("Response Message Header \n\n" + response.Content.Headers + "\n");
        // Get the response
        var customerJsonString = await response.Content.ReadAsStringAsync();
        Console.WriteLine("Your response data is: " + customerJsonString);

        // Deserialise the data (include the Newtonsoft JSON Nuget package if you don't already have it)
        var deserialized = JsonConvert.DeserializeObject<IEnumerable<Customer>>(custome‌​rJsonString);
        // Do something with it
    }

Modifiez votre WebApi pour ne pas utiliser votre classe Response mais plutôt un IEnumerable de Customer. Utilisez la classe de réponse HttpResponseMessage.

Votre WebAPI ne devrait exiger que:

[HttpGet, Route("GetAll")]
public IEnumerable<Customer> GetAllCustomers()
{
    var allCustomers = repository.GetAll();
    // Set a breakpoint on the line below to confirm
    // you are getting data back from your repository.
    return allCustomers;
}

Ajout de code pour une classe de réponse générique basée sur la discussion dans les commentaires bien que je vous recommande toujours de ne pas le faire et d'éviter d'appeler votre classe Response. Vous devriez plutôt retourner codes d'état HTTP au lieu du vôtre. A 200 Ok, 401 Unauthorized, etc. Aussi cet article sur la façon de retourner les codes d'état HTTP.

    public class Response<T>
    {
        public bool IsSuccess { get; set; }
        public string Message { get; set; }
        public IEnumerable<T> ResponseData { get; set; }

        public Response(bool status, string message, IEnumerable<T> data)
        {
            IsSuccess = status;
            Message = message;
            ResponseData = data;
        }
    }
19
Murray Foxcroft

OU vous pouvez convertir sur le même appel

  TResponse responseobject = response.Content.ReadAsAsync<TResponse>().Result;
            responseJson += "hostResponse: " + JsonParser.ConvertToJson(responseobject);
            //_logger.Debug($"responseJson : {responseJson}", correlationId);
0
Taran