web-dev-qa-db-ja.com

C#でHttpClientを使用してWeb API応答を読み取る方法

私はwebapiを初めて使用し、いくつかのアクションがあり、Responseというカスタムクラスを返す小さなwebapiを開発しました。

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

アクション付きの私のwebapi

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

今私が立ち往生しているのは、webapiアクションから返された応答データを読み取り、応答クラスからjsonを抽出する方法がわからないということです。 jsonを取得した後、そのjsonを顧客クラスにdeserializeできますか。

これは私の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();   
}

コードの整理を手伝ってください

1)webapiがクライアント側で返す応答クラスを取得する方法

2)応答クラスからjsonを抽出する方法

3)クライアント側でjsonを顧客クラスにデシリアライズする方法

ありがとう

編集

私はこのコードを使用していますが、それでもエラーが発生します。

    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 エラーメッセージ:

タイプ 'Newtonsoft.Json.JsonSerializationException'の例外がNewtonsoft.Json.dllで発生しましたが、ユーザーコードでは処理されませんでした

追加情報:現在のJSONオブジェクト(例:{"name": "value"})をタイプ 'WebAPIClient.Response []'にデシリアライズできません。タイプを正しくデシリアライズするにはJSON配列(例[1,2,3])が必要です。

応答がこのエラーを引き起こすのはなぜですか?

7
Monojit Sarkar

クライアントで、コンテンツの読み取りを含めます。

    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
    }

Responseクラスではなく、IEnumerableCustomerを使用するようにWebApiを変更します。 HttpResponseMessage応答クラスを使用します。

WebAPIに必要なものは次のとおりです。

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

コメント内の議論に基づいて汎用応答クラスのコードを追加しましたが、これを行わず、クラスResponseの呼び出しを避けることをお勧めします。独自のコードではなく、 HTTPステータスコード を返す必要があります。 200 OK、401 Unauthorizedなど。また、 この投稿 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

または、同じ通話で変換できます

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