Recently in my company we wanted to use IHttpClientFactory
with our web app. But the problem was IHttpClientFactory
was originally meant to be used with Asp.Net Core and not MVC 5. So I had to find a workaround that to be able to use it with older MVC applications. So in this post I’m going to describe how I’ve done that.
The Problem with using HttpClient as opposed to IHttpClientFactory
The problem associated with using many instance of HttpClient
in our app doesn’t come from HttpClient
itself. But it comes from HttpMessageHandler
and it’s lifetime. When we new up many instances of HttpClient
in our app with a using statement, what happen is the HttpClient
is disposed of but the socket stays open. This can lead to socket exhaustion problem, you can read more about this issue here.
Installing the Necessary Packages for IHttpClientFactory
IHttpClientFactory
can be used easily with Asp.Net Core. But if we want to use it with Asp.Net MVC we need to take some extra steps. Even thought most of the article and post related to using IHttpClientFactory
is for using it with Asp.Net Core, we can also use it with older MVC projects. But we need to make sure that project can support .Net Standard. So let’s see what packages are necessary for us to be able to use it with Asp.Net MVC.
The first package to install is Microsoft.Extensions.Http. This package is dependent on many other package so don’t get surprised if you saw many other package also installed with it. We also going to need microsoft.extensions.hosting package to use the built in Asp.Net Core container. The reason we need to do that is the fact that there’s a lot of other dependencies involved when we want to resolve the IHttpClientFactory
. If this was not the case we didn’t need to use the built in DI container of Asp.Net Core. Because we could directly inject whatever that is necessary to receive a functioning IHttpClientFactory
.
Let’s take a look at the source code of the method use to register a IHttpClientFactory
.
In this example use a new instance of HttpClientMappingRegistry
. But if we try to do the same in our code we get an error because the class is internal and we can’t create an instance of it ourselves. There are many other classes here that have the same internal access modifier. So what we plan to do is to register the instance of the factory in Asp.Net Core container. Get an instance from the container and register it as a singleton in our Ninject container. I’m going to show you how to do that in next section.
Using IHttpClientFactory with Ninject
In this section I’m going to create a Ninject module that act as a bridge between Asp.Net Core container and our Ninject container. In this case we’re going to have two DI container in our application which can have its own problems. But if we use it in a organized and focused way when it’s necessary, I think we’re going to be fine. So the code of the Niject module looks like something like this.
What we do here is we create a new container, register the dependencies needed to resolve the IHttpClientFactory
. We do that by using AddHttpClient
, there are other ways to register an instance such as Named Clients, Typed Clients etc. You can find more info on how to use the factory differently here. After that we register a singleton instance of the factory using Ninject’s ToConstant
method.
Now that we registered the singleton instance of the factory, we can go ahead and use it in our application like so.
By using the factory we can have our old pattern on using a HttpClient
within using statement but with some crucial difference. Now even though we get a new instance of HttpClient
the underlying HttpMessageHandler
might be the same. The factory is going to manage that for us, this illustrated best by the image we see in MSDN page.
This post was particularly focused on using the IHttpClientFactory
with older version of Asp.Net MVC, but there are other ways to use it. Also there are some configuration that can be done such as implementing retry and logging policy. They are not covered in this post to keep it more focused on the problem we were trying to solve. Also I’ve created a working repository with an MVC 5 app using the code I described, you can find it here.
Further Readings
Use IHttpClientFactory to implement resilient HTTP requests
Make HTTP requests using IHttpClientFactory in ASP.NET Core
HttpClientFactory in ASP.NET Core 2.1 (Part 1)
HttpClientFactory in ASP.NET Core 2.1 (Part 3)
HttpClientFactory in ASP.NET Core 2.1 (Part 4)
Summary
In this post, we saw the problems associated with using non-static HttpClient and how we can use IHttpClientFactory
to fix that. I also explained how we can use the .Net Standard package for IHttpClientFactory to use it with older MVC applications. The GitHub repository for the sample code used in this post can be found here.