Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get data from external API with a asp.net core API

I'm learning to create APIs using ASP.NET core, in this I came up with a problem, I'm trying to execute a request for an external API using my API, but I do not know how to execute the request and return the JSON of the request, any help?

The flow of the application looks something like this:

SPA -> AspNet Core WEB API -> External API

What I've done so far:

[Route("api/[Controller]")]
    public class RankingsController : Controller
    {
        private readonly IRankingRepository _rankingRepository;

        public RankingsController(IRankingRepository rankingRepo)
        {
            _rankingRepository = rankingRepo;
        }

        [HttpGet("{id}", Name = "GetRanking")]
        public IActionResult GetById(long id)
        //Here is where I want to make the requisition
        }

    }

I need to make the request for this API:

http://api.football-data.org/v1/competitions/{id}/leagueTable

In the ID location, I need to pass a parameter that comes from the request made in my API;

Any help for this problem?

Sorry for not being such a complex question.

Thanks!!

like image 448
Jefferson Bruchado Avatar asked Nov 15 '18 18:11

Jefferson Bruchado


1 Answers

You could use an HttpClient instance to achieve what you want. However, I always find easier to use RestSharp though.

That, of course will depend on your constraints but assuming you have none for this case, you could use RestSharp to make the call to the external API:

Install it:

Install-Package RestSharp

Usage:

using RestSharp;

[HttpGet("{id}", Name = "GetRanking")]
public async Task<IActionResult> GetByIdAync(long id)
{
    var client = new RestClient($"http://api.football-data.org/v1/competitions/{id}/leagueTable");
    var request = new RestRequest(Method.GET);
    IRestResponse response = await client.ExecuteAsync(request);

    //TODO: transform the response here to suit your needs

    return Ok(data);
}

To consume the rest response from RestSharp you must use the response.Content property.

You could, for example, deserialize it to Json, manipulate it to fit your needs and return the required data to your API caller.

Example:

Let's say I'd like to get the rankings for the Premier League 2017/18 (Id = 445):

I'll get a lot of help below from the legendary Newtonsoft.Json package and a little of jpath syntax but I'll assume you've already used both :)

Create a couple models to hold the values to be returned to the API caller:

public class LeagueTableModel
{
    public string LeagueCaption { get; set; }

    public IEnumerable<StandingModel> Standings { get; set; }
}
public class StandingModel
{
    public string TeamName { get; set; }

    public int Position { get; set; }
}

Implement the below method in the service class, injected to your controller through DI/IoC to avoid coupling and increase testability (as we all know we should do right?). I'm assuming this class is RankingRepository in your sample:

public RankingRepository: IRankingRepository 
{
    public Task<LeagueTableModel> GetRankingsAsync(long id)
    {
        var client = new RestClient($"http://api.football-data.org/v1/competitions/{id}/leagueTable");
        var request = new RestRequest(Method.GET);
        IRestResponse response = await client.ExecuteAsync(request);
        if (response.IsSuccessful)
        {
            var content = JsonConvert.DeserializeObject<JToken>(response.Content);

            //Get the league caption
            var leagueCaption = content["leagueCaption"].Value<string>();

            //Get the standings for the league.
            var rankings = content.SelectTokens("standing[*]")
                .Select(team => new StandingModel
                {
                    TeamName = (string)team["teamName"],
                    Position = (int)team["position"]
                })
                .ToList();

            //return the model to my caller.
            return new LeagueTableModel
            {
                LeagueCaption = leagueCaption,
                Standings = rankings
            };
        }

        //TODO: log error, throw exception or do other stuffs for failed requests here.
        Console.WriteLine(response.Content);

        return null;
    }
}

Use it from the controller:

[Route("api/[Controller]")]
public class RankingsController : Controller
{
    private readonly IRankingRepository _rankingRepository;

    public RankingsController(IRankingRepository rankingRepo)
    {
        _rankingRepository = rankingRepo;
    }

    [HttpGet("{id}", Name = "GetRanking")]
    public Task<IActionResult> GetByIdAsync(long id)
        //Here is where I want to make the requisition
        var model = await _rankingRepository.GetRankingsAsync(id);

        //Validate if null
        if (model == null)
            return NotFound(); //or any other error code accordingly. Bad request is a strong candidate also.

        return Ok(model);
    }
}

Hope this helps!

like image 196
Karel Tamayo Avatar answered Oct 21 '22 19:10

Karel Tamayo