When working in applications in ASP.NET Core you might often need to invoke the Web API action methods using HttpClient to check if the endpoints are working fine. To achieve this, you would typically instantiate HttpClient and use the instance to invoke your action methods. However, there are certain downsides to using HttpClient directly, mainly having to do with managing the lifetimes of the instances manually.
You can avoid these downsides by using IHttpClientFactory to create your HttpClient instances. Introduced in .NET Core 2.1, IHttpClientFactory provides a central place to name, configure, and create HttpClient instances and manages the pooling and lifetimes of the instances automatically.
I’ve discussed HttpClient and HttpClientFactory in an earlier
article
here. This article further discusses HttpClient and IHttpClientFactory with code examples to illustrate the concepts covered. To work with the code examples provided, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can
download Visual Studio 2019 here
.
Launch the Visual Studio IDE.
Click on “Create new project.”
In the “Create new project” window, select “ASP.NET Core Web Application” from the list of templates displayed.
Click Next.
In the “Configure your new project” window, specify the name and location for the new project.
Optionally check the “Place solution and project in the same directory” check box, depending on your preferences.
Click Create.
In the “Create a New ASP.NET Core Web Application” window shown next, select .NET Core as the runtime and ASP.NET Core 3.1 (or later) from the drop-down list at the top.
Select “Web Application (Model-View-Controller)” as the project template to create a new ASP.NET Core MVC application.
Ensure that the check boxes “Enable Docker Support” and “Configure for HTTPS” are unchecked as we won’t be using those features here.
Ensure that Authentication is set to “No Authentication” as we won’t be using authentication either.
Click Create.
Following these steps should create a new ASP.NET Core MVC project in Visual Studio 2019. In the new project, create a new API controller and save it using the default name, i.e., ValuesController. We’ll use this project in the sections that follow.
HttpClient challenges
Although the HttpClient class doesn’t
implement the IDisposable interface
directly, it extends the System.Net.Http.HttpMessageInvoker class, which does implement IDisposable. Nevertheless, when working with HttpClient instances, you shouldn’t be disposing of them. Although you can call the Dispose method on an HttpClient instance, it is not a recommended practice.
What should you do instead? One option is to make the HttpClient instance static or wrap a non-static instance of the HttpClient inside a custom class and make it a singleton class. But a better alternative is to use IHttpClientFactory to retrieve an instance of HttpClient and then use the instance for calling action methods.
IHttpClientFactory and HttpClientFactory
IHttpClientFactory is an interface that is implemented by the DefaultHttpClientFactory class, which is an opinionated factory. The DefaultHttpClientFactory implements the IHttpClientFactory and IHttpMessageHandlerFactory interfaces. IHttpClientFactory was introduced to provide ASP.NET Core with excellent built-in support for creating, caching, and disposing of HttpClient instances.
Note that HttpClientFactory (discussed in my
earlier article
) is just a helper to create HttpClient instances configured with the handlers provided. This class has the following methods:
public static HttpClient Create(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers)
HttpMessageHandler pipeline = CreatePipeline(innerHandler, handlers);
return new HttpClient(pipeline);
Source: https://github.com/aspnet/HttpClientFactory/blob/master/src/Microsoft.Extensions.Http/IHttpClientFactory.cs
Both HttpClientFactory and IHttpClientFactory were introduced to better manage the lifetime of HttpMessageHandler instances.
Why use IHttpClientFactory?
When you dispose of a HttpClient instance, the connection remains open for up to four minutes. Further, the number of sockets that you can open at any point in time has a limit — you can’t have too many sockets open at once. So when you use too many HttpClient instances, you might end up exhausting your supply of sockets.
Here’s where IHttpClientFactory comes to the rescue. You can take advantage of IHttpClientFactory to create HttpClient instances for invoking HTTP API methods by adhering to the best practices to avoid issues faced with HttpClient. The primary goal of IHttpClientFactory in ASP.NET Core is to ensure that HttpClient instances are created using the factory while at the same time eliminating socket exhaustion.
Register an IHttpClientFactory instance in ASP.NET Core
You can register an instance of type IHttpClientFactory in the ConfigureServices method of the Startup class by calling the AddHttpClient extension method on the IServiceCollection instance as shown in the code snippet given below.
public void ConfigureServices(IServiceCollection services)
services.AddControllersWithViews();
services.AddHttpClient();
Inject an IHttpClientFactory instance to your controllers in ASP.NET Core
You can then inject an IHttpClientFactory instance to your controllers as shown in the code snippet given below.
private IHttpClientFactory _httpClientFactory;
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger,
IHttpClientFactory httpClientFactory)
_logger = logger;
_httpClientFactory = httpClientFactory;
//Your action methods go here
Call your action methods using HttpClient in ASP.NET Core
To create an HttpClient using IHttpClientFactory, you should call the CreateClient method. Once the HttpClient instance is available, you can use the following code in the Index action method of the HomeController class to invoke the Get method of the ValuesController class.
public async Task<IActionResult> Index()
HttpClient httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri("http://localhost:1810/");
var response = await httpClient.GetAsync("/api/values");
string str = await response.Content.ReadAsStringAsync();
List<string> data = JsonSerializer.Deserialize<List<string>>(str);
return View(data);
Use IHttpClientFactory to create and manage HttpClient instances in ASP.NET Core
There are several ways you can use IHttpClientFactory in your application. These include using IHttpClientFactory directly, using named clients, and using typed clients.
The basic or general usage pattern—i.e., using IHttpClientFactory directly—has already been discussed in the preceding sections. Refer to the section “Register an IHttpClientFactory instance” that discusses how you can register an HttpClient instance.
Using named clients
If you would like to use HttpClient instances with different configurations, named clients is a good choice. The following code snippet illustrates how you can create a named client.
services.AddHttpClient("github", c =>
c.BaseAddress = new Uri("https://api.github.com/");
c.DefaultRequestHeaders.Add("Accept",
"application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "This is a test user agent");
Using typed clients
A typed client is defined using a custom class that wraps an HttpClient instance, encapsulating the logic for calls to all of the endpoints over the HTTP protocol. The following code snippet illustrates how a custom HttpClient class can be defined.
public class ProductService : IProductService
private IHttpClientFactory _httpClientFactory;
private readonly HttpClient _httpClient;
private readonly string _baseUrl = "http://localhost:1810/";
public ProductService(HttpClient httpClient)
_httpClient = httpClient;
public async Task<Catalog> GetAllProducts()
_httpClient = _httpClientFactory.CreateClient();
_httpClient.BaseAddress = new Uri(_baseUrl);
var uri = "/api/products";
var result = await _httpClient.GetStringAsync(uri);
return JsonConvert.DeserializeObject<Product>(result);
The following code snippet shows how you can register your custom typed HttpClient.
services.AddHttpClient<IProductService, ProductService>();
Add MessageHandlers to the pipeline in ASP.NET Core
A Message handler is a class that extends the HttpMessageHandler class, accepts an HTTP request, and returns an HTTP response. If you would like to build your own message handler, you should create a class that extends the DelegatingHandler class.
You can add HttpMessageHandlers to the request processing pipeline. If you’re using a named client, you can use the following code in the ConfigureServices method of the Startup class to add message handlers to the pipeline.
public void ConfigureServices(IServiceCollection services)
services.AddHttpClient("github", c =>
c.BaseAddress = new Uri("https://api.github.com/");
.AddHttpMessageHandler<DemoHandler>();
services.AddTransient<DemoHandler>();
IHttpClientFactory is an opinionated factory that has been available since .NET Core 2.1. If you use IHttpClientFactory to create your HttpClient instances, then the pooling and lifetime of the underlying HttpClientMessagehandler instances are managed for you automatically. IHttpClientFactory also takes care of common concerns such as logging.
How to use the ProblemDetails middleware in ASP.NET Core
How to create route constraints in ASP.NET Core
How to manage user secrets in ASP.NET Core
How to build gRPC applications in ASP.NET Core
How to redirect a request in ASP.NET Core
How to use attribute routing in ASP.NET Core
How to pass parameters to action methods in ASP.NET Core MVC
How to use API Analyzers in ASP.NET Core
How to use route data tokens in ASP.NET Core
How to use API versioning in ASP.NET Core
How to use Data Transfer Objects in ASP.NET Core 3.1
How to handle 404 errors in ASP.NET Core MVC
How to use dependency injection in action filters in ASP.NET Core 3.1
How to use the options pattern in ASP.NET Core
How to use endpoint routing in ASP.NET Core 3.0 MVC
How to export data to Excel in ASP.NET Core 3.0
How to use LoggerMessage in ASP.NET Core 3.0
How to send emails in ASP.NET Core
How to log data to SQL Server in ASP.NET Core
How to schedule jobs using Quartz.NET in ASP.NET Core
How to return data from ASP.NET Core Web API
How to format response data in ASP.NET Core
How to consume an ASP.NET Core Web API using RestSharp
How to perform async operations using Dapper
How to use feature flags in ASP.NET Core
How to use the FromServices attribute in ASP.NET Core
How to work with cookies in ASP.NET Core
How to work with static files in ASP.NET Core
How to use URL Rewriting Middleware in ASP.NET Core
How to implement rate limiting in ASP.NET Core
How to use Azure Application Insights in ASP.NET Core
Using advanced NLog features in ASP.NET Core
How to handle errors in ASP.NET Web API
How to implement global exception handling in ASP.NET Core MVC
How to handle null values in ASP.NET Core MVC
Advanced versioning in ASP.NET Core Web API
How to work with worker services in ASP.NET Core
How to use the Data Protection API in ASP.NET Core
How to use conditional middleware in ASP.NET Core
How to work with session state in ASP.NET Core
How to write efficient controllers in ASP.NET Core
Angular 19 to make standalone the default for components
The standalone feature lets developers build apps that do not depend on NgModule and is now the recommended way to write Angular code.
By Paul Krill
Sep 04, 2024
2 mins
Web Development
Angular
Development Libraries and Frameworks
What is HTTP/3? The next-generation web protocol
HTTP/3 breaks from HTTP/2 by adopting the QUIC protocol over TCP. Here's a first look at the new standard and what it means for web developers.
By Matthew Tyson
Sep 04, 2024
8 mins
Web Development
Software Development
Ruby on Rails gets better production defaults
Version 7.2 of the longstanding web framework arrives with improved production defaults and a new dev container config.
By Paul Krill
Aug 14, 2024
2 mins
Web Development
Programming Languages
Google unveils Flutter GPU API, Dart updates
Flutter GPU, available in an early preview, is a low-level graphics API for building rendering packages from scratch using Dart and GLSL.
By Paul Krill
Aug 07, 2024
3 mins
Mobile Development
Web Development
Development Tools
Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.
He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as
Community Credit Winner
several times.
He is the author of eight books and more than 500 articles. Many of his articles have been featured at
Microsoft’s Official Site on ASP.Net
.
He was a speaker at the
Spark IT 2010 event
and at the
Dr. Dobb’s Conference 2014
in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the
SSWUG Virtual Conference
, which is held twice each year.
More from this author
analysis
Using the Pinecone vector database in .NET
By Simon Bisson
Sep 12, 2024
7 mins
Microsoft .NET
Generative AI
Development Tools
how-to
Using PostgreSQL as a vector database in RAG
By Nitin Borwankar
Sep 12, 2024
15 mins
PostgreSQL
Generative AI
Artificial Intelligence
feature
Oracle CloudWorld 2024: Latest news and insights
By Anirban Ghoshal
Sep 12, 2024
7 mins
Cloud Computing
video
How to implement "modes" in software, with a game as an example
Sep 12, 2024
4 mins
Python