IHttpClientFactory Patterns: Using Typed Clients from Singleton Services Exploring an approach to reuse transient typed clients within singleton services

I’ve been following IHttpClientFactory for some time and have created a number of blog posts on the various features based on sample applications. Since then; with the release of ASP.NET Core 2.1 now available, I’ve begun using IHttpClientFactory in real production applications. In this post, I want to start covering some patterns I’ve begun to apply as I develop my applications.

This time I want to look at an issue regarding the scope of typed clients. This is based on something I’ve now directly encountered and that was raised as a comment on an earlier post by a reader named Yair.

When defining typed clients in your ConfigureServices method, the typed service is registered with transient scope. This means that a new instance is created by the DI container every time one is needed. The reason this occurs is that a HttpClient instance is injected into the typed client instance. That HttpClient instance is intended to be short lived so that the HttpClientFactory can ensure that the underlying handlers (and connections) are released and recycled.

This works in cases where you plan to consume the typed service from another transient service. A common place to use these in ASP.NET Core will be places such as Controllers for example. That works as expected since the controller is created by the framework for each request.

However, what if you want to use the typed client within a singleton service? That presents a problem. If this was allowed it would be created and injected once, and then held onto by the singleton service. This is not the behaviour we want.

Originally, when asked by Yair about how to use HttpClientFactory in singleton services I suggested instead using the named client approach and then injecting the IHttpClientFactory directly to your singleton service. From there, you can call CreateClient on the factory within methods on that singleton service, so that for each invocation, a new HttpClient is created for only a short lifetime.

The problem is that if we don’t get the typed client behaviour where we can encapsulate the work necessary to interact with a third party API as a service. Instead, we would have to make a service that depends on the IHttpClientFactory as I suggested above and then pass that into the necessary places in our code.

Having now tackled this in a real project where I am essentially building an SDK around an internal API that I’ve developed I have reassessed the options. What I ended up doing was using the typed client approach, but also providing my own factory which can return instances of that typed client. This is actually very simple to do by leveraging the DI service provider directly.

Here is an example of a typed client and its interface:

I won’t dive deeply into how this service works. It’s a typed client and you can read my earlier post about named and typed clients for more information.

In short; this service expects to have a HttpClient instance injected when it is created by the DI container. It then wraps the logic needed to call various endpoints of a remote API. Within this service, we can include the code needed to validate the response and deserialise the returned content from the request.

We can register the typed client in our ConfigureServices method as follows:

At this point, we have a typed client which can be consumed from other transient services and controllers. To make this accessible to singleton services in our application we can add a basic factory.

Here we have created a basic interface for an IConfigurationServiceFactory which defines a single GetConfigurationService method.

The implementation takes an IServiceProvider in its constructor, which will be injected by DI. With access to the service provider, we can use it to return an instance of IConfigurationService from the GetConfigurationService method. As this is a transient typed client, a new instance will be returned each time this method is called.

In ConfigureServices, we can register the factory with DI as a singleton:

As this is a singleton, we can consume this from any class where we need access to an instance of the typed client, even if that class is registered with singleton scope in DI.

The important thing here is that we don’t create an instance of the IConfigurationService and hold onto it for the lifetime of the singleton service. We can hold the IConfigurationServiceFactory and then we must use that whenever a method needs to get access to the IConfigurationService.

I’m sure there may be other ways to achieve similar results but I’m fairly happy with this approach for now.

Related Posts

Part 1 – An introduction to HttpClientFactory
Part 2 – IHttpClientFactory – Defining Named and Typed Clients
Part 3 – IHttpClientFactory – Outgoing request middleware with handlers
Part 4 – IHttpClientFactory – Integrating with Polly for transient fault handling

ASP.NET Core Dependency Injection – Registering Implementations Using Delegates Using the delegate implementation factory extension methods with Microsoft.Extensions.DependencyInjection

Today I want to continue my series (see links at the end of this post) of posts focusing on the Microsoft dependency injection library included by default in new ASP.NET Core projects. In this post I wanted to dive into another lesser known capability of the default DI library.

I was recently reviewing some code where the developer had brought in StructureMap as the container for an ASP.NET Core application. My colleague was using it in place of the Microsoft.Extensions.DependencyInjection package since he wanted to take advantage of some more advanced registrations. StructureMap extends the abstractions for DI provided by Microsoft and so can be easily swapped in as the DI container.

However, when reviewing the code I noticed that we could actually achieve the required registrations using the built in DI instead, removing the extra dependency on StructureMap. Also, from some performance benchmarks I’ve seen, I believe that the Microsoft DI is performing pretty well when compared to StructureMap. NOTE: I can’t seem to locate the source I’d previously read. If/when I track it down I’ll update this post with a link.

The exact example I was looking at is a bit too complicated to explain and demonstrate here. Instead I have put together a simpler example based loosely on the real-world case. In our application we were taking a dependency on an internal library that at this point we didn’t want to modify. One of the classes we wanted to use and resolve via DI looked a little like this…

We wanted to be able to register the IIndexNameProvider type, with the implementation returning this external WeekBasedElasticIndexNameProvider class. However, this presented a problem, since the constructor expects a string parameter defining the baseIndexName. We weren’t in a position to adjust this class and so my colleague had used StructureMap in order to register it as follows

In this registration the IElasticsearchConfig is loaded from DI and it’s IndexNamePrefix property is used to supply the baseIndexName required by the WeekBasedElasticIndexNameProvider. The IDateTimeProvider is also surfaced via DI and passed into the constructor for the WeekBasedElasticIndexNameProvider instance.

It turns out that the Microsoft DI is capable of a similar behaviour. There are overloads of the Add extension methods (e.g. AddSingleton) which accept a Func<IServiceProvider, TService> as the implementation factory. This delegate is expected to return an instance of a suitable object for the registration. To achieve the above registration using the Microsoft DI we can use this code to register our service…

The delegate that this extension method takes as a parameter expects us to return an implementation of the IIndexNameProvider interface. It expects an IIndexNameProvider since that is what has been defined in the generic parameter for the AddSingleton method. In the delegate we get access to an IServiceProvider which we can use to access other registered services.

This delegate will be called the first time that an instance of IIndexNameProvider is required as a dependency on any of our other services registered in the DI container. At that point, the delegate is executed; retrieving the IElasticsearchConfig and IDateTimeProvider from the IServiceProvider. It uses the IElasticsearchConfig to get the required IndexNamePrefix value.

Now that we have the IndexNamePrefix value and an IDateTimeProvider, we can construct and return an instance of the WeekBasedElasticIndexNameProvider which implements IIndexNameProvider. Using this pattern we were able to default back to the Microsoft DI.

It’s likely to be fairly infrequent that you’ll need to register services using delegates in this way, but should you need to do so it’s perfectly possible. Using this approach you can use other services registered in DI to configure or control the implementation that the DI container builds.

Other posts in this series

ASP.NET Core Dependency Injection – How to Register Generic Types
ASP.NET Core Dependency Injection – Registering Multiple Implementations of an Interface

ASP.NET Core Dependency Injection – Registering Multiple Implementations of an Interface

In a previous post I covered registering generic types with Dependency Injection. This is one of the less common (and less documented) ways in which services could be registered with the Microsoft DI library. It turns out that you can do more with the DI available in the Microsoft.Extensions.DependencyInjection package than it may first appear.

Another “advanced” pattern that can be achieved is to register multiple concrete implementations for an interface. These can later be injected as an IEnumerable of that interface. In this post we’ll explore a quick example of how we can do that.

Let’s first discuss when and why you might want to do this. The example I have is based on a service I’ve been involved with previously. This service is responsible for reading messages from a Amazon SQS queue, enriching them and then saving them to ElasticSearch. Based on the property values in the message it conditionally enriches the data. Initially we only had a couple of possible enrichers, but over time we’ve added more.

The way we decided to implement this was to define an IEnricher interface. That interface looks a little like this:

There are two methods on the interface. The first is called CanEnrich and this will take the message object and determine if this enricher can do enrichment on the message. The second method, Enrich, then performs the actual enrichment of the message.

We can define zero or more implementations of this interface for the different enriching activities we may want to perform.

Here’s example of an enricher:

This enricher tries to lookup the city for any failed login messages coming through our queue. It can only do this if the IP Address is present.

And here’s another :

This enricher populates a DayOfWeek property, which is then used for aggregating in ElasticSearch. It can only do this if the incoming message contains a Date.

Both of are quite basic and contrived examples. The functionality isn’t that important here though.

The enrichers can now be registered with the ServiceCollection wherever that happens in your application:

It’s worth making it clear that the implementations will be added in the order they are registered. They will be returned in that same order when injected into calling code. Depending on your requirements, this may be useful and important. For this example we don’t really care what order we get them in.

To make use of these enrichers we can have them injected wherever we require them and DI is available. Since we’ve registered more than one instance, we ask the DI framework for an IEnumerable<IEnricher> which we can then enumerate over to access all implementations.

A simplified example of this in a caller would look like this:

Here I filter to only the enrichers which can enrich the message we are processing. Then I call the Enrich method on each one in turn.

Where this pattern proves particularly useful is if we imagine we now want to add another enricher. All we have to do is create a class which implements the interface and then ensure it is registered with DI. Now when our caller runs, that enricher will be included in the IEnumerable<IEnricher> which is injected. Our consuming code will make use of the new enricher without any further code changes.

The ASP.NET Core framework uses this same pattern in a number of places. One which I’ve covered in the past is the IHostedService interface. This allows you to define one or more “background” services to run whilst you application is alive. As with my enricher example, all you have to do is create a class implementing IHostedService and then register it with DI. When the application starts it will fire up any registered IHostedService instances in order.

Other posts in this series

ASP.NET Core Dependency Injection – How to Register Generic Types
ASP.NET Core Dependency Injection – Registering Implementations Using Delegates

ASP.NET Core Dependency Injection – How to Register Generic Types Exploring how generic types can be registered with the built-in Microsoft DI container

Since its release, ASP.NET Core has shipped with a “basic” Dependency Injection (DI) container included. This supports the functionality required to run the framework which was built from the ground up to support the use of DI throughout.

The ASP.NET documentation describes some general information about the use of DI in ASP.NET Core.

The documentation for the DI container (ServiceProvider) claims that its quite basic and not a replacement for more fully featured containers such as AutoFac or StructureMap for example. In my experience, for many of my requirements it has proved quite sufficient. In this short post I want to explore a less common registration requirement that may exist for some developers.

Imagine a scenario where you want to register a generic interface and a generic implementation with the ASP.NET Core DI container. In ASP.NET Core itself, an example of this use case is the ILogger<T> interface. We can ask for an ILogger<T> in constructors of our Controllers for example, where T is the Type that the logger will be logging for.

To put this more concretely; if we have a ValuesController and we want to log caught errors from our Actions, we can require an ILogger<ValuesController> in our constructor for the ValuesController. When the controller is constructed by the framework it will receive an implementation of the generic Logger<T> for our provided Type parameter. Under the covers the ILoggerFactory will use the type name to return the appropriate Logger. Messages logged via that logger will then include the full name of the Type (Namespace.ValuesController) when logged to the console for example.

A common way to register services with the ServiceCollection is using the generic extension methods. To add a Singleton registration for an interface and it’s concrete type for example we can call…

serviceCollection.AddSingleton<IService, MyService>();

The signature for the AddSingleton method is…

public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection serviceswhere TService : class where TImplementation : class, Tservice

This works well for most scenarios but doesn’t work if we want to register generic services.

For a slightly contrived example, let’s say we have an interface like this…

And an implementation like this…

We want to be able to ask for an IThing<SomeType> in the constructor of a consumer which will get the correct GenericThing<SomeType> injected.

In this case we can use a different extension method on the ServiceCollection that accepts the types as parameters. Our registration would then look like this…

We now have our generic interface and implementation registered correctly. We can now consume this via DI wherever we need it injected.

Other posts in this series

ASP.NET Core Dependency Injection – Registering Multiple Implementations of an Interface
ASP.NET Core Dependency Injection – Registering Implementations Using Delegates

A Reminder to Take Care when Registering Dependencies

I looked into a “fun” little problem yesterday where we were seeing occasional errors in some of our ASP.NET Core code which calls down into the ASP.NET Core Identity UserManager. We were getting a range of NullReferenceException and ObjectDisposedExceptions as well as various exceptions from Npgsql.NpgsqlConnection (we use Postgres rather than SQL in this project) stating things such as “Connection already open”.

The issue was presenting itself within some authentication and authorisation code we have which wraps and extends the ASP.NET Core Identity UserManager and SignInManager functionality. We use ASP.NET Identity over a PostGres database for our user store but include some application specific functionality with our own code. We have our own AuthenticationManager and UserManager classes, both of which take dependencies on the underlying Microsoft.AspNetCore.Identity classes.

These originally got registered in in the ConfigureServices method of the Startup.cs class as follows:

services.AddSingleton<IAuthenticationManager, AuthenticationManager>();
services.AddSingleton<IUserManager, UserManager>();

The constructor for our AuthenticationManager looks a bit like this:

public AuthenticationManager(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager)
{
   // setup our authentication manager here
}

Do you see the problem?

The issue here is the singleton registration. While our classes themselves have no state and could be shared between requests, the dependencies on Microsoft.AspNetCore.Identity.UserManager<T> and Microsoft.AspNetCore.Identity.SignInManager<T> have to be considered.

If we take a look at where these are registered within the Microsoft.AspNetCore.Identity source we can see the following:

services.TryAddScoped<UserManager<TUser>, UserManager<TUser>>();
services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();

They are added using the scoped lifetime which means they expect to be created once per request. They themselves depend on an IUserStore which is registered with the scoped lifetime as well.

As a result, the singleton registration of our AuthenticationManager was trying to hang onto dependencies to objects for the entire application lifetime, where those dependencies only expected to live for the request scope. Sometimes they seemed to get a different database context and hence the “Connection already open” errors we saw. Sometimes the dependencies had been disposed of by the time they got called by our code and as such we saw the various exceptions being thrown. In some cases we seemed to still have access to the UserManager but the context underneath was null. I won’t dive into this tool deeply, but it was apparent that we should really make the registration of our classes scoped as well. This way, they are created once per request, the same as their dependencies. We changed the registration code to the following:

services.AddScoped<IAuthenticationManager, AuthenticationManager>();
services.AddScoped<IUserManager, UserManager>();

This resolved the errors we were seeing immediately. It was an annoying oversight although fortunately it was fairly easy to guess at the cause. The various errors all suggested that we having some issues with the lifetime of the  dependencies. This case has been a reminder to carefully consider the lifetimes of service registrations as it can produce some unexpected errors and behaviour.

The Microsoft documentation even includes a large warning about scoped services – “The main danger to be wary of is resolving a Scoped service from a singleton. It’s likely in such a case that the service will have incorrect state when processing subsequent requests.” – Oh how true this is!

Happy dependency injecting!