- Using HttpRequestMessage Object
- Named Client
- Typed Client
Typed Client:
Typed Client technique is to implement or create a separate entity or class file per API domain. So all Http communication implementations are registered in a specific class per API domain. In this approach, each entity or class will be injected with 'System.Net.Http.HttpClient' object by the 'HttpClienFacotry'. So in this approach, we will not use 'HttpClientFactory' directly like we did for 'Named Client' and 'Using HttpRequestMessage Object' techniques.
In simple words for consuming one third-party rest API need to create a specific class for it, if we have 'n' number of rest APIs to consume in our project then we need to create 'n' number of classes to implement the HttpClientFactory logic specific to the domains of rest APIs.
HttpClientFactory Request Flow:
ThirdParty Test APIs:
JSONPlaceholder:
https://jsonplaceholder.typicode.com/
Dummy Rest API:
http://dummy.restapiexample.com/
Create A .Net Core Sample API Project:
Install NewtonSoft.Json Package:
CLI Command:
dotnet add package Newtonsoft.Json
PackageManager:
Install-Package Newtonsoft.Json
Create A Typed Client Of JSONPlaceHolder Rest API:
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using TypedClientApi.Model; namespace TypedClientApi.RestCalls { public class JsonPlaceHolderClient { public readonly HttpClient _httpClient; public JsonPlaceHolderClient(HttpClient httpClient) { httpClient.BaseAddress = new Uri("https://jsonplaceholder.typicode.com"); _httpClient = httpClient; } } }
- 'JsonPlaceHolderClient.cs' is a Typed Client of 'JsonPlaceHolder' API, all GET, POST, DELETE action methods will implemented in this class.
- 'System.Net.Http.HttpClient' object injected into our typed client. In this approach, HttpClientFacotry will not be used directly.
- In this constructor we can configure our HttpClient object with 'domain', 'default-headers','default-keys', etc. These default configurations can also be configured at the 'Startup.cs' file also.
namespace TypedClientApi.Model { public class Todo { public int UserId { get; set; } public int Id { get; set; } public string Title { get; set; } public bool Completed { get; set; } } }Now let's implement 'Todos' endpoint get method as follows:
public async Task<List<Todo>> GetTodos() { var response = await _httpClient.GetAsync("/todos"); if (response.IsSuccessStatusCode) { string responseString = await response.Content.ReadAsStringAsync(); List<Todo> todos = JsonConvert.DeserializeObject<List<Todo>>(responseString); return todos; } return new List<Todo>(); }
- (Line 3) HttpClient object is used to trigger the 'Todo' endpoint. The HttpClient object is made of all asynchronous operations like 'GetAsync', 'PostAsync', 'DeleteAsync' etc. Since we assigned the domain name at the time of constructor initialization, so for endpoints can be declared with a relative path.
- So on receiving the successful response, we deserialize the response to the object.
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddHttpClient<JsonPlaceHolderClient>(); }Let's write a 'Test' controller endpoint to consume this 'Todo' API as follows:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using TypedClientApi.Model; using TypedClientApi.RestCalls; namespace TypedClientApi.Controllers { [Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { private readonly JsonPlaceHolderClient _jsonPlaceHolderClient; public TestController(JsonPlaceHolderClient jsonPlaceHolderClient) { _jsonPlaceHolderClient = jsonPlaceHolderClient; } [HttpGet] [Route("all-todos")] public async Task<IActionResult> GetTodos() { List<Todo> todos = await _jsonPlaceHolderClient.GetTodos(); return Ok(todos); } } }
- (Line: 17) 'JsonPlaceHolderClient' rest-client injected to our test controller.
- (Line: 22-28) get action method to fetch all todos
Create A Type Client Of DummyExampleRestAPI:
using Newtonsoft.Json; using System.Collections.Generic; namespace TypedClientApi.Model { public class Employee { [JsonProperty(PropertyName = "id")] public string Id { get; set; } [JsonProperty(PropertyName = "employee_name")] public string EmployeeName { get; set; } [JsonProperty(PropertyName = "employee_salary")] public string EmployeeSalary { get; set; } [JsonProperty(PropertyName = "employee_age")] public string EmplyeeAge { get; set; } [JsonProperty(PropertyName = "profile_image")] public string ProfileImage { get; set; } } public class DummyExampleApiResult { public string Status { get; set; } public List<Employee> Data { get; set; } } }Now let's implement 'DummyExampleRestAPI' typed client as below:
RestCalls/DummyExampleRestClient.cs:
using Newtonsoft.Json; using System; using System.Net.Http; using System.Threading.Tasks; using TypedClientApi.Model; namespace TypedClientApi.RestCalls { public class DummyExampleRestClient { private readonly HttpClient _httpClient; public DummyExampleRestClient(HttpClient httpClient) { httpClient.BaseAddress = new Uri("http://dummy.restapiexample.com"); _httpClient = httpClient; } public async Task<DummyExampleApiResult> GetEmployees() { var response = await _httpClient.GetAsync("/api/v1/employees"); if (response.IsSuccessStatusCode) { string responseString = await response.Content.ReadAsStringAsync(); DummyExampleApiResult employees = JsonConvert.DeserializeObject<DummyExampleApiResult>(responseString); return employees; } return new DummyExampleApiResult(); } } }Now register 'DummyExampleRestClient' in startup.cs as below:
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddHttpClient<JsonPlaceHolderClient>(); services.AddHttpClient<DummyExampleRestClient>(); }Now inject our 'DummyExampleRestClient' into the TestController as below:
Controllers/TesController.cs:
private readonly JsonPlaceHolderClient _jsonPlaceHolderClient; private readonly DummyExampleRestClient _dummyExampleRestClient; public TestController( JsonPlaceHolderClient jsonPlaceHolderClient, DummyExampleRestClient dummyExampleRestClient) { _jsonPlaceHolderClient = jsonPlaceHolderClient; _dummyExampleRestClient = dummyExampleRestClient; }Now add get action methods to fetch employee data as below:
[HttpGet] [Route("all-employee")] public async Task<IActionResult> GetEmployees() { DummyExampleApiResult employees = await _dummyExampleRestClient.GetEmployees(); return Ok(employees); }
Now run the application and checks the JSON response data of employee endpoint like below:
Default HttpClient Configuration At Startup.Cs:
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddHttpClient<JsonPlaceHolderClient>(client => { client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com"); //client.DefaultRequestHeaders // client.Timeout // client.DefaultRequestVersion }); services.AddHttpClient<DummyExampleRestClient>(client => { client.BaseAddress = new Uri("http://dummy.restapiexample.com"); //client.DefaultRequestHeaders // client.Timeout // client.DefaultRequestVersion }); }Now we can remove the default configurations from the constructor in the typed clients as below:
namespace TypedClientApi.RestCalls { public class JsonPlaceHolderClient { public readonly HttpClient _httpClient; public JsonPlaceHolderClient(HttpClient httpClient) { _httpClient = httpClient; } } } namespace TypedClientApi.RestCalls { public class DummyExampleRestClient { private readonly HttpClient _httpClient; public DummyExampleRestClient(HttpClient httpClient) _httpClient = httpClient; } } }Finally, we have implemented a sample using the Typed Client technique in .net core application.
Support Me!
Buy Me A Coffee
PayPal Me
Comments
Post a Comment