In this article, we are going to implement different HttpClient techniques to consume API calls in minimal API.
The different HttpClient techniques that we are going to explore are like:
- Register HttpClient Object Explicitly In DI(Dependency Injection Service)
- Named Client
- Type Client
- HttpRequestMessage Object
Create A .NET6 Minimal API Project:
Let's create a .Net6 Minimal API sample project to accomplish our demo. We can use either Visual Studio 2022 or Visual Studio Code(using .NET CLI commands) to create any.Net6 application. For this demo, I'm using the 'Visual Studio Code'(using the .NET CLI command) editor.
CLI command For Minimal API Project
dotnet new webapi -minimal -o Your_Project_Name
dotnet new webapi -minimal -o Your_Project_Name
Create A Third Party API Response Model:
Here I'm going to use a free third-party rest API that is "https://jsonplaceholder.typicode.com/posts". So to receive the response let's create a response model like 'Post.cs'.
Program.cs:(Add Post.cs class At bottom of Program.cs)
class Post { public int UserId { get; set; } public int Id { get; set; } public string Title { get; set; } public string Body { get; set; } }
Register HttpClient Object Explicitly In DI(Dependency Injection Service):
Initialize the HttpClient object with a configuration like 'domain', 'default headers', etc in the Dependency injection services. After that, we can pass the HttpClient object as an input parameter to the delegate handler of our Minimal API endpoint. The only negative impact of this approach is when we have multiple different domain APIS to consume this approach fails to work. Because the last HttpClient object registration will override all other HttpClient registration. So this technique is only good when our application consumes a single third-party API domain.
Let's initialize and register the HttpClient in DI.
Program.cs:
builder.Services .AddScoped(hc => new HttpClient { BaseAddress = new Uri("https://jsonplaceholder.typicode.com/") });
- Here to the 'HttpClient' instance register the 'BaseAddress' value is the domain name of the third-party API.
Program.cs:
app.MapGet("explicit-http-client", async (HttpClient http) => { return await http.GetFromJsonAsync<List<Post>>("/posts"); });
- So here we can observe our minimal API endpoint delegate handler method has input parameter of type 'HttpClient'. So instance of 'HttpClient' created by the framework with the help of IHttpClientFactory.
Named Client:
The HttpClient object will be generated or invoked with the 'names'. So while registering the client we have to specify the 'name' for the HttpClient. Using the same 'name' we can get the instance of HttpClient from the IHttpClientFactory. This approach supports multiple HttpClient registrations with their respective registered names.
Program.cs:
builder.Services .AddHttpClient("jsonplaceholder", client => { client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/"); });
- Here we registered HttpClient instance with a name('jsonplaceholder'). This same name will be used by the IHttpClientFactory to create the HttpClient instance.
Program.cs:
app.MapGet("named-http-client", async(IHttpClientFactory _httpClientFactory) => { var httpClient = _httpClientFactory.CreateClient("jsonplaceholder"); return await httpClient.GetFromJsonAsync<List<Post>>("/posts"); });
- (Line: 2) Using the registered name('jsonplaceholder') we are creating the HttpClient instance from the IHttpClientFactory.
Typed Client:
Each external API domain will have a separate class to inject the HttpClient object. This class will be registered as a type of HttpClient in the DI services.
So let's create a typed class that is specific to a domain like 'PostHttpClient.cs'.
Program.cs:(Add PostHttpClient At Bottom Of Program.cs)
class PostHttpClient { private HttpClient _httpClient; public PostHttpClient(HttpClient httpClient) { _httpClient = httpClient; } public async Task<List<Post>> AllPosts() { return await _httpClient.GetFromJsonAsync<List<Post>>("/posts"); } }
- Here our 'PostHttpClient' typed class is specific to domain ("jsonplaceholder.typicode.com"). So API calls related domain will be implemented in this class.
Program.cs:
builder.Services .AddHttpClient<PostHttpClient>(client => { client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/"); });Now let's create a minimal API endpoint to consume the external API using a typed client.
Program.cs:
app.MapGet("typed-http-client", async(PostHttpClient postHttpClient) => { return await postHttpClient.AllPosts(); });
- Here we can observe our typed client(PostHttpClient) is passed as an input parameter to the delegate handler of our endpoint.
HttpRequestMessage Object:
In this approach HttpRequestMessage object will be used to configure settings like 'domain', 'headers', 'payload', etc, this object will be used by the HttpClient object to invoke or consume the rest API.
Program.cs:
builder.Services.AddHttpClient();
- Here just register the plain 'AddHttpClient' service.
Program.cs:
app.MapGet("http-request-object", async (IHttpClientFactory httpClientFactory) => { var request = new HttpRequestMessage(HttpMethod.Get, "https://jsonplaceholder.typicode.com/posts"); var httpClient = httpClientFactory.CreateClient(); var response = await httpClient.SendAsync(request); return await response.Content.ReadFromJsonAsync<List<Post>>(); });
- So here we can observe all the API-related configurations are taken place in the 'HttpRequestMessage' object.
- Using IHttpClientFactory generates the HttpClient instance.
- Using the 'HttpClient.SendAsnync' method invoke the API by passing the 'HttpRequestMessage' object as an input parameter.
Support Me!
Buy Me A Coffee
PayPal Me
Video Session:
Wrapping Up:
Hopefully, I think this article delivered some useful information on implementing different HttpClient techniques to consume api in Minimal API. I love to have your feedback, suggestions, and better techniques in the comment section below.
will you be posting the source code for your .net 6 videos to github?
ReplyDeleteNice
ReplyDelete