user12065090
user12065090

Reputation:

C# Accessing APIs

I followed a tutorial (https://www.youtube.com/watch?v=aWePkE2ReGw) to try and call APIs using C#, and while it worked, my attempts to modify it for my own projects failed miserably. Despite my best efforts and trying various different links on the same website, they all return failure.

I was able to access it with python no problem, so the problem seems confined to C#. I have the microsoft.aspnet.webapi.client installed, as well as json. It compiles and runs, just returns failure.

https://dbd.tricky.lol/apidocs/

Here's the code:

namespace API_Test
{
    // class used to initialize the httpclient
    public class ApiHelper
    {
        public static HttpClient? ApiClient { get; set; }

        public static void InitializeClient()
        {
            ApiClient = new HttpClient();
            ApiClient.DefaultRequestHeaders.Accept.Clear();
            ApiClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
        }
    }

    // used to hold the result
    class ShrineModel
    {
        public double ID { get; set; }
    }

    // used for processing results
    class ShrineResultModel
    {
        public ShrineModel? Results { get; set; }
    }

    // used to access the api
    class ShrineProcessor
    {
        public static async Task<ShrineModel> LoadShrineInformation()
        {
            string url = "https://dbd.tricky.lol/api/shrine";

            using (HttpResponseMessage response = await ApiHelper.ApiClient.GetAsync(url))
            {
                if (response.IsSuccessStatusCode)
                {
                    ShrineResultModel result = await response.Content.ReadAsAsync<ShrineResultModel>();

                    return result.Results;
                }
                else
                {
                    // ALWAYS ENDS UP HERE
                    Console.WriteLine("Failure");
                    Console.ReadKey();
                    throw new Exception(response.ReasonPhrase);
                }
            }
        }
    }

    // main
    public class API_Test 
    {
        static async Task Main()
        {
            ApiHelper.InitializeClient();
            var ShrineInfo = await ShrineProcessor.LoadShrineInformation();
            Console.WriteLine(ShrineInfo.ID);
        }
    }
}

Best case scenario I get a json output with all the information found at the link. What I'm getting is a false response from "IsSuccessStatusCode"

I've tried various other endpoints available from the same website. Other APIs have worked. But I can't get this one to.

Upvotes: 0

Views: 112

Answers (1)

Charles Han
Charles Han

Reputation: 2010

I ran your code against the API and there are a couple of issues to fix.

1. 403 Forbidden

You got response.IsSuccessStatusCode false because the API endpoint requires a User-Agent header. This is to block any web crawler bots.

To fix that you just need to add this code,

ApiClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0");

2. Wrong JSON data model

You must model the JSON response structure so the deserialization can work properly.

The JSON response:

{
  "id": 666,
  "perks": [
    {
      "id": "Aftercare",
      "bloodpoints": 100000,
      "shards": 2000
    },
    {
      "id": "BeastOfPrey",
      "bloodpoints": 100000,
      "shards": 2000
    },
    {
      "id": "DeadHard",
      "bloodpoints": 100000,
      "shards": 2000
    },
    {
      "id": "Nemesis",
      "bloodpoints": 100000,
      "shards": 2000
    }
  ],
  "start": 1672185600,
  "end": 1672790399
}

So your ShrineResultModel should be like this:

    public class Perk
    {
        public string id { get; set; }
        public int bloodpoints { get; set; }
        public int shards { get; set; }
    }

    public class ShrineResultModel
    {
        public int id { get; set; }
        public List<Perk> perks { get; set; }
        public int start { get; set; }
        public int end { get; set; }
    }

Update your code to deserialize the JSON response:

if (response.IsSuccessStatusCode)
{
   ShrineResultModel result = await response.Content.ReadFromJsonAsync<ShrineResultModel>();
   return result;
}

The actual result:

enter image description here

Upvotes: 3

Related Questions