Search code examples
c#asp.netjson.net

How do I consume an API using ASP.net Framework?


Sample Json:

{
  "success": true,
  "status": 200,
  "data": [
    {
      "ProfileID": "1001",
      "Name": "Jane Doe",
      "HomePhone": "555-1212",
      "Address1": "123 Elm St"
    },
    {
      "ProfileID": "1002",
      "Name": "Rick Fox",
      "HomePhone": "555-1213",
      "Address1": "123 Ok St"
    }
  ]
}

My code so far:

using Newtonsoft.Json;

private void popGrid()
{
   var client = new HttpClient();
   client.BaseAddress = new Uri("http://the-api/");
   var responseTask = client.GetAsync("member-list");
   responseTask.Wait();
   var result = responseTask.Result;
   if (result.IsSuccessStatusCode)
   {
      var read_response = responseTask.Result.Content.ReadAsStringAsync();
      read_response.Wait();
      var read_result = read_response.Result;

      dynamic response = JsonConvert.DeserializeObject(read_result);
      var success = response.success;
      var status = response.status;
      var data = response.data;

      // List<Root> myDeserializedClass = JsonConvert.DeserializeObject<List<Root>>(data);

      if ((bool)success)
      {
         GridView1.DataSource = data;
         GridView1.DataBind();
      }
   }

}

public class Root
{
   public string ProfileID { get; set; }
   public string Name { get; set; }
   public string HomePhone { get; set; }
   public string Address1 { get; set; }
}

The Errors: If I run the code as written, it runs through all the way without issue. However when the page renders I get an ugly error:

    Type 'Newtonsoft.Json.Linq.JValue' in Assembly 'Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' is not marked as serializable.

Buried in the Stack Trace is one line that gives a clue(to me):

    [ArgumentException: Error serializing value '1001' of type 'Newtonsoft.Json.Linq.JValue.']

So then I the added the (commented) line that uses the Root class. However, if I un-comment that line and run the code, I get the following error:

    Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject<System.Collections.Generic.List<Root>>(string)' has some invalid arguments'

The above error seems to indicate that JsonConvert.DeserializeObject won't accept the var 'data' as an input. Any thoughts would be greatly appreciated.

Based on the accepted answer this is my final working solution:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

const string theAPI = "http://the-api/";
const string otherAPI = "http://other-api/";

protected void Button2_Click(object sender, EventArgs e)
{
   DataTable dt = GetDataTableFromAPI(theAPI, "member-list");
   if (dt.Rows.Count > 0)
   {
      GridView1.DataSource = dt;
      GridView1.DataBind();
      GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;
   }
   else
   {
      // nothing found
   }
}

public DataTable GetDataTableFromAPI(string api, string endPoint) 
{
   var client = new HttpClient();
   client.BaseAddress = new Uri(api);
   var response = client.GetAsync(endPoint).Result;
   if (response.IsSuccessStatusCode)
   {
      var json = response.Content.ReadAsStringAsync().Result;
      var jsonParsed = JObject.Parse(json);
      var success = jsonParsed["success"];
      var status = jsonParsed["status"];
      if ((bool)success)
      {
         DataTable dt = jsonParsed["data"].ToObject<DataTable>();
         return dt;
      }
   }
   return new DataTable();
}

Solution

  • it is better to create async method , but if you can not , you have to fix your code

        var response = client.GetAsync(api).Result;
        if (response.IsSuccessStatusCode)
        {
         var json = response.Content.ReadAsStringAsync().Result;
         var jsonParsed=JObject.Parse(json);
         var success = jsonParsed["success"];
          var status = jsonParsed["status"];
          List<Root> data = jsonParsed["data"].ToObject<List<Root>>();
        
          //or in this case you don't need any custom classes at all
    
           DataTable data = jsonParsed["data"].ToObject<DataTable>();
          
        
          if ((bool)success)
          {
             GridView1.DataSource = data;
             GridView1.DataBind();
          }
    
         }