External Api Call Using Rest Sharp
Tags: csharp, beginners, dotnetcore
Published: 2023-12-09 09:21:30

##### External Api Calls Using Rest Sharp in C#
In today's world of Microservices, it is very common to have multiple services that are communicating with each other. In this tutorial we will create a new webapi project and add a service to make external api calls using RestSharp.

##### Prerequisites
🎯 .Net installed on your machine
🎯 Visual Studio Code or Visual Studio 
🎯 Postman or any other tool to make api calls

##### Project Setup

```bash
mkdir RestSharpDemo
cd RestSharpDemo
```

##### Create a new sln file

```bash
dotnet new sln -n RestSharpDemo
```

##### Create a new webapi project

```bash
dotnet new webapi -n RestSharpDemo.Api
```

##### Add the project to the solution
    
```bash
dotnet sln add **/*.csproj
```

##### Add the following nuget packages to the project in the RestSharpDemo.Api folder
    
```bash
cd RestSharpDemo.Api
dotnet add package RestSharp
```

##### Create a Services folder in the RestSharpDemo.Api project

```bash
mkdir Services
cd Services
```

##### Create an interface for the service for the external api

```bash
touch IExternalApiService.cs
```

```csharp
using RestSharp; // comes from the nuget package

namespace RestSharpDemo.Api.Services
{
    public interface IExternalApiService<T> where T : class
    {

        Task<List<T>> GetAll(string subURL, Dictionary<string, string> queryParams = null!);
        Task<T> GetById(Int64 Id, string subURL);
        Task<RestResponse> Add(T model, string subURL);
        Task<RestResponse> Update(T model, string subURL);
        Task<RestResponse> Delete(Int64 Id, string subURL);
    }
}
```

##### Create a class for the service for the external api

```bash
touch ExternalApiService.cs
```

```csharp
using RestSharp; // comes from the nuget package

namespace RestSharpDemo.Api.Services
{
       public class ExternalApiService<T> : IExternalApiService<T> where T : class
    {
        private readonly RestClient _client;
        private readonly IConfiguration _configuration;


        public ExternalApiService(IConfiguration configuration)
        {
            _configuration = configuration;
            _client = new RestClient(_configuration["ExternalApi:BaseUrl"] ?? string.Empty);
        }


        public async Task<List<T>> GetAll(string subURL, Dictionary<string, string> queryParams = null!)
        {
            var request = new RestRequest(subURL, Method.Get)
            { RequestFormat = DataFormat.Json };

            if (queryParams != null)
            {
                foreach (var param in queryParams)
                {
                    request.AddQueryParameter(param.Key, param.Value);
                }
            }

            var response = await _client.ExecuteAsync<List<T>>(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception($"Error calling external api: {response.ErrorMessage}");
            }

            return response.Data!;
        }

        public async Task<T> GetById(Int64 Id, string subURL)
        {
            var request = new RestRequest($"{subURL}/{Id}", Method.Get)
            { RequestFormat = DataFormat.Json };

            var response = await _client.ExecuteAsync<T>(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception($"Error calling external api: {response.ErrorMessage}");
            }

            return response.Data!;
        }

        public async Task<RestResponse> Add(T model, string subURL)
        {
            var request = new RestRequest(subURL, Method.Post);


            request.AddJsonBody(model);

            var response = await _client.ExecuteAsync(request);

            //check server not available
            if (response.StatusCode == HttpStatusCode.ServiceUnavailable)
            {
                throw new Exception($"Server not available: {response.ErrorMessage}");
            }

            if (response.StatusCode != HttpStatusCode.Created)
            {
                throw new Exception($"Error calling external api: {response.ErrorMessage}");
            }

            return response;
        }

        public async Task<RestResponse> Update(T model, string subURL)
        {
            try
            {
                var request = new RestRequest(subURL, Method.Put)
                { RequestFormat = DataFormat.Json };

                request.AddJsonBody(model);

                var response = await _client.ExecuteAsync(request);

                if (response.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new Exception($"Post not found: {response.ErrorMessage}");
                }


                return response;
            }
            catch (Exception ex)
            {
                throw new Exception($"Error calling external api: {ex.Message}");
            }
        }

        public async Task<RestResponse> Delete(Int64 Id, string subURL)
        {
            var request = new RestRequest($"{subURL}/{Id}", Method.Delete);

            var response = await _client.ExecuteAsync(request);

            Console.WriteLine($"response.StatusCode: {response.StatusCode}");
            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception($"Error calling external api: {response.ErrorMessage}");
            }

            return response;
        }
    }
}

```

##### Add the following to the Program.cs file in the RestSharpDemo.Api project

```csharp
using RestSharpDemo.Api.Services;

var builder = WebApplication.CreateBuilder(args);

// We used typeof because we are using generics in the ExternalApiService
builder.Services.AddSingleton(typeof(IExternalApiService<>), typeof(ExternalApiService<>));

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();



app.Run();

```

##### Add the following to the appsettings.json file in the RestSharpDemo.Api project

```json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "ExternalApi": {
    "BaseUrl": "https://jsonplaceholder.typicode.com"
  },
  "AllowedHosts": "*"
}
```

##### Create a new controller in the Controllers folder in the RestSharpDemo.Api project

```bash
touch PostsController.cs
```

```csharp

using Microsoft.AspNetCore.Mvc;

namespace RestSharpDemo.Api.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class PostsController : ControllerBase
    {
        private readonly IExternalApiService<Post> _externalApiService;

        public PostsController(IExternalApiService<Post> externalApiService)
        {
            _externalApiService = externalApiService;
        }

         [HttpGet]
        public async Task<IActionResult> GetAll([FromQuery] Dictionary<string, string> queryParams = null!)
        {
            string _subURL = "posts";
            var result = await _externalApiService.GetAll(_subURL, queryParams);
            var output = result
                .Take(10)
                .OrderByDescending(x => x.Id).
                ToList();
            return Ok(output);
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> GetById(Int64 id)
        {
            string _subURL = "posts/";
            var result = await _externalApiService.GetById(id, _subURL);
            return Ok(result);
        }

        [HttpPost]
        public async Task<IActionResult> Add(PostDto post)
        {
            string _subURL = "posts/";
            var result = await _externalApiService.Add(post, _subURL);
            return Ok(result.Content);
        }

        [HttpPut]
        public async Task<IActionResult> Update(PostDto post)
        {
            string _subURL = "posts/";
            var result = await _externalApiService.Update(post, _subURL);
            return Ok(result.Content);
        }

        [HttpDelete("{id}")]
        public async Task<IActionResult> Delete(Int64 id)
        {
            string _subURL = "posts/";
            var result = await _externalApiService.Delete(id, _subURL);
            return Ok(result.Content);
        }
    }
}

```

##### Create a new model in the Models folder in the RestSharpDemo.Api project

```bash
touch Post.cs
```

```csharp

namespace RestSharpDemo.Api
{
    public class Post
    {
        public Int64 Id { get; set; }
        public Int64 UserId { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }
    }
}

```

##### Run the project

```bash
dotnet run --project RestSharpDemo.Api/RestSharpDemo.Api.csproj
```

##### Open a browser and navigate to the following url

- https://localhost:5001/swagger/index.html


##### Conclusion
This is a very simple example of how to make external api calls using RestSharp. You can use this as a starting point to build your own service to make external api calls. Thank you for reading and happy coding! 🚀