0

Forgive my lack of knowlegde, I'm a database guy although I dabbled a bit with C# a while back. I am trying to figure how to get this API running.

The API I'm trying to consume is from https://rapidapi.com/api-sports/api/api-nba/. There is barely any documentation to guide me.

Here's my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using unirest_net.http;
using unirest_net;

namespace NBA_test
{
    class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Start ...");

            Task<HttpResponse<MyClass.RootObject>> response = Unirest.get("https://api-nba-v1.p.rapidapi.com/gameDetails/5162")
            .header("X-RapidAPI-Host", "api-nba-v1.p.rapidapi.com")
            .header("X-RapidAPI-Key", "myKey")
            .asJsonAsync<MyClass.RootObject>();

            var status = response.Status;

            Console.WriteLine("End ....");
        }
    }

    public class MyClass
    {
        public class Result
        {
            public string seasonYear { get; set; }
            public int gameId { get; set; }
            public string arena { get; set; }
        }

        public class RootObject
        {
            public List<Result> results { get; set; }
        }
    }
}

var status goes from Created to Running and then that's it, program closes. No error message but I don't know how to get the JSON out of this API. I know I'm missing something but don't know what.

Crna Krv
  • 127
  • 2
  • 11
  • Is your question how to use the async/await pattern (`Unirest.get` appears to be async since it returns `Task`)? If so, [this question](https://stackoverflow.com/questions/14455293/how-and-when-to-use-async-and-await) and [this question](https://stackoverflow.com/questions/9208921/cant-specify-the-async-modifier-on-the-main-method-of-a-console-app) might help you. – ProgrammingLlama Jun 03 '19 at 02:23
  • This is a way too fast. Just give your program a chance to make this request. Add `Console.ReadKey();` line at the end of your `Main` method. – vasily.sib Jun 03 '19 at 03:03
  • @cma-krv did you check the answers? – Ali Bahrami Jun 08 '19 at 09:18
  • @Ali Bahrami yes I did, none of them work out off the bat so I am trying to figure this out. Been very busy with family and work lately but will come back to it soon. – Crna Krv Jun 11 '19 at 03:27
  • Ok so I switched from an async call to a sync call. I keep getting a "System.InvalidCastException: 'Unable to cast object of type 'System.IO.MemoryStream' to type 'RootObject'.'" error message. – Crna Krv Jun 28 '19 at 03:34

4 Answers4

1

You are in a console application with a sync main method. You should not call an async method inside a sync method. I made your async call into a sync call :

    public static void Main(string[] args)
    {
        Console.WriteLine("Start ...");

        var response = Unirest.get("https://api-nba-v1.p.rapidapi.com/gameDetails/5162")
        .header("X-RapidAPI-Host", "api-nba-v1.p.rapidapi.com")
        .header("X-RapidAPI-Key", "myKey")
        .asJson<RootObject>();

        var status = response.Status;

        Console.WriteLine("End ....");
    }

you still might ask where is your deserialized JSON?

According to Unirest docs:

Response Upon recieving a response Unirest returns the result in the form of an Object, this object should always have the same keys for each language regarding to the response details.

.Code - HTTP Response Status Code (Example 200) .Headers - HTTP Response Headers .Body - Parsed response body where applicable, for example JSON responses are parsed to Objects / Associative Arrays. .Raw - Un-parsed response body

Basically, you can access your result like this:

if (response.Code == 200) // Success, OK in HTTP Codes
{
  response.Body; // which body has the type of MyClass.RootObject
}

The complete example:

        public static void Main(string[] args)
        {
            Console.WriteLine("Start ...");

            var response = Unirest.get("https://api-nba-v1.p.rapidapi.com/gameDetails/5162")
            .header("X-RapidAPI-Host", "api-nba-v1.p.rapidapi.com")
            .header("X-RapidAPI-Key", "myKey")
            .asJson<RootObject>();

            if (response.Code == 200) // Success, OK in HTTP Codes
            {
              response.Body; // which body has the type of MyClass.RootObject
            }

            Console.WriteLine("End ....");

            Console.ReadLine(); // to force command line stay up for an input and not close applicaiton immediately aftter runing it.
        }

Update 1:

Here is a live and working of Unirest on .NET Fiddle:

https://dotnetfiddle.net/EZDopa

Ali Bahrami
  • 5,935
  • 3
  • 34
  • 53
  • I switched to a sync call but I keep getting a **"System.InvalidCastException: 'Unable to cast object of type 'System.IO.MemoryStream' to type 'RootObject'**.'" error message. – Crna Krv Jun 29 '19 at 03:34
  • @CrnaKrv I think you are right. I updated the code and create a living example on .NET Fiddle, please take a look https://dotnetfiddle.net/EZDopa – Ali Bahrami Jun 29 '19 at 06:45
  • I did the changes but I still get the same type of message: **Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'System.IO.MemoryStream' to type 'NBA_test.RootObject'. at unirest_net.http.HttpResponse`1..ctor(HttpResponseMessage response) at unirest_net.http.HttpClientHelper.Request[T](HttpRequest request) at unirest_net.request.HttpRequest.asJson[T]()** – Crna Krv Jun 29 '19 at 15:06
0

As the others pointed out you need to add some kinda wait statment. I did many calls to api that took time to process in one of my applications. Based on the others comments I updated to allow for logic to be executed while your waiting for the call to come back. an edit for your code is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using unirest_net.http;
using unirest_net;

namespace NBA_test
{
class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Start ...");
        //the added Wait() causes the thread to hold until the task is finished.
        Task<HttpResponse<MyClass.RootObject>> response = Unirest.get("https://api-nba-v1.p.rapidapi.com/gameDetails/5162")
        .header("X-RapidAPI-Host", "api-nba-v1.p.rapidapi.com")
        .header("X-RapidAPI-Key", "myKey")
        .asJsonAsync<MyClass.RootObject>();


        //if need to perform other logic while you are waiting
        while(response.Status == TaskStatus.Running)
        {
         // perform other logic like gui here
        }
        var status = response.Status;

        Console.WriteLine("End ....");
    }
}

public class MyClass
{
    public class Result
    {
        public string seasonYear { get; set; }
        public int gameId { get; set; }
        public string arena { get; set; }
    }

    public class RootObject
    {
        public List<Result> results { get; set; }
    }
}

}

  • Adding `.Wait` will cause a deadlock to the application and it's not recommended. – Ali Bahrami Jun 03 '19 at 15:17
  • @AliBahrami yes i agree the Wait will cause the application to hang up, though reason I suggested it is in the context of his example it would be either calling .Wait() or Looping til the results from the call are fulfilled. – Ricky Tucker Jr Jun 04 '19 at 04:48
  • `Unirest` already got `sync` methods, so no need to call `async` one. – Ali Bahrami Jun 04 '19 at 05:45
0

You can use httpClient

   using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
            var response = httpClient.GetStringAsync(new Uri(url)).Result;
            var releases = JArray.Parse(response);
        }
Jinto John
  • 365
  • 4
  • 22
0

Turns out the API's documentation is flawed. I managed to make it work by simply using string (and Newtonsoft's Json.NET). Thx for the help @AliBahrami. Code looks like this now:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using unirest_net.http;
using unirest_net;
using Newtonsoft.Json.Linq;

namespace NBA_test
{
    public class Program
    {

        public static void Main(string[] args)
        {

            Console.WriteLine("Start of Program...");

            HttpResponse<string> response = Unirest.get("https://api-nba-v1.p.rapidapi.com/gameDetails/9999")
            .header("X-RapidAPI-Host", "api-nba-v1.p.rapidapi.com")
            .header("X-RapidAPI-Key", "myKey")
            .asJson<string>();

            var result = response.Body;

            JObject parsedString = JObject.Parse(result);

            RootObject myGame = parsedString.ToObject<RootObject>();

            // Get game id
            Console.WriteLine(myGame.results[0].gameId);

            Console.WriteLine("End of Program....");
        }
    }
}
Crna Krv
  • 127
  • 2
  • 11