How to use HttpClientFactory Inside Program.cs

Full source code here.

Over the past week I have written a few articles about HttpClientFactory and dependency injection in .NET Core 2.1. There is one scenario I didn’t deal with – calling a HttpClient from inside the Main method in Program.cs. If you have read my previous post you will probably know how do it, but in case you landed on this post from a search here is how to do it.

In Startup.cs, add the HttpClientFactory to the service collection.

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("OpenBreweryDb", client =>
    {
        client.BaseAddress = new Uri("https://api.openbrewerydb.org/breweries/");
        client.DefaultRequestHeaders.Add("Accept", "application/json");
    });
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

In Progam.cs I split the building the webHost from running it so I can get at the service collection.

public static void Main(string[] args)
{
    IWebHost webHost = CreateWebHostBuilder(args).Build();
    CallSomeRemoteService(webHost.Services);
    webHost.Run();
}

Then I grab a HttpClientFactory from the service collection and a HttpClient from inside the HttpClientFactory.

private static void CallSomeRemoteService(IServiceProvider serviceProvider)
{
    var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();
    var httpClient = httpClientFactory.CreateClient("OpenBreweryDb");
    var response = httpClient.GetAsync("?by_state=Massachusetts&by_name=night").Result;
    if (response.IsSuccessStatusCode)
    {
        var breweries = response.Content.ReadAsAsync<List<Brewery>>().Result;
    }
}

That’s it, easy when you know how.

Full source code here.

How to Dependency Inject a Service from Startup back in Program

Full source code here.

While writing some recent blog posts on HttpClientFactory I had to work with some of the obscure features of ServiceCollection and dependency injection in .NET Core 2.1. One of the things I wanted to do was get at an instance of a token generator from the service collection inside the Main method in Program.cs.

Some time ago I wrote a post about using the ServiceCollection from Program.cs and while that worked for the example I gave, there are cases where it would not depending on the specifics of what scope you are using, and in the case of a singleton, how you instanced it. When it goes wrong you end up with multiple instances of a singleton, multiple DI containers and plenty of unpredictable results. It’s too painful to explain all the variations, you can read a bit more here where David Folwer says “hosting current[ly] creates 3 service providers and its extremely broken in the general case”.

How to Pass a Service from ServicesCollection into Program
In this approach none there are none of the problems outlined above, only one instance of the singleton is every instantiated.

In Startup.cs add all the services you want inside ConfigureServices(..).

public void ConfigureServices(IServiceCollection services)
{
    services.AddMemoryCache();
    services.AddSingleton<ITokenGenerator, TokenGenerator>();
}

In Program.cs, I have the usual CreateWebHostBuilder(..), no changes.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)	
        .UseStartup<Startup>();	

But in Main, instead of

CreateWebHostBuilder(args).Build().Run();

I split building the WebHost from running the WebHost.

public static void Main(string[] args)
{		
    IWebHost webHost = CreateWebHostBuilder(args).Build();
    var tokenGenerator = webHost.Services.GetService<ITokenGenerator>();
    string token =  tokenGenerator.GetToken();
    System.Console.WriteLine(token);
    webHost.Run();
}
  • Line 3 creates the webHost, but doesn’t run it
  • this in turn instantiates the startup class and runs ConfigureServices(..)
  • Line 4 reaches into the ServiceCollection for the ITokenGenerator service that was setup in ConfigureServices(..)
  • Lines 5 and 6, use the TokenGenerator service to get a token a print it to screen
  • Line 7 runs the WebHost and the application starts up

Full source code here.

Dynamically Updating the Request Header of a HttpClientFactory Generated HttpClient, Part 2

Full source code here.

This is a alternative to the approach described in a previous post.

On a slack channel there was some discussion around the use of a little known extension method on HttpClientBuilder, ConfigureHttpClient. Using this extension method provides another way to dynamically alter the header of a HttpClient provided by the factory.

In ConfigureServices(..) I setup the two services I need, the MemoryCache and the TokenGenerator.

Then, where I configure the HttpClientFactory I call the ConfigureHttpClient, pass it an Action that takes the ServiceProvider and the HttpClient I’m configuring.

Inside the Action, I take a TokenGenerator from the service collection and then add the token to the client header.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMemoryCache();
    services.AddSingleton<ITokenGenerator, TokenGenerator>();

    services.AddHttpClient("RemoteServer", client =>
    {
        client.BaseAddress = new Uri("http://localhost:5000/api/");
        client.DefaultRequestHeaders.Add("Accept", "application/json");
    }).ConfigureHttpClient((serviceProvider, client) =>
    {
        ITokenGenerator tokenGenerator = serviceProvider.GetService<ITokenGenerator>();
        client.DefaultRequestHeaders.Add("Token", tokenGenerator.GetToken());
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

That’s it, simpler than the approach in the previous post.

Full source code here.

Dynamically Updating the Request Header of a HttpClientFactory Generated HttpClient, Part 1

Full source code here.

There are some subtle issues in the way I use DI in this post, see here for an alternative if you don’t want to follow this approach

While using the HttpClientFactory I hit a scenario where I needed to update the value of a token passed in the header of requests, the token changed frequently, so I had to repeatedly update it throughout the lifetime of my application.

You have a couple of options for this, the first is to do it after you have taken a HttpClient from the factory at the point where you make your outbound request, this is straightforward, but now everywhere use a HttpClient you have to be able to get a new token. For some this might be fine, and you can use –

    httpClient.DefaultRequestHeaders.Add("Token", _tokenGenerator.GetToken());

Doing it with HttpClientFactory
The better approach is to put all this logic in the Startup.cs and update the header when the factory returns a new HttpClient, now everywhere you use the HttpClient gets the updated token without any work for you.

In my example case I have a token generator and memory cache. If there is a token in the cache, that one is used, if not the token generator generates and stores the new token in the cache for specified period.

In my Startup.cs all I need is this –

services.AddHttpClient("RemoteServer", client =>
{
    client.BaseAddress = new Uri("http://localhost:5000/api/");
    client.DefaultRequestHeaders.Add("Accept", "application/json");
    client.DefaultRequestHeaders.Add("Token", TokenGenerator.GetToken());
});

Read on to see how to wire everything up.

A little known feature of .NET Core is the ability to DI from Program.cs into Startup.cs, I have written about this before in Using Dependency Injection with Startup.cs in ASP.NET Core and am using it again here.

In Program.cs I add a memory cache and a token generator to the service collection.

Adding to the service collection this way can have some unexpected side effects, check this post for an alternative approach.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .ConfigureServices(cs => cs.AddMemoryCache())
    .ConfigureServices(cs => cs.AddSingleton<ITokenGenerator, TokenGenerator>())
        .UseStartup<Startup>();

In Startup.cs I pass a ITokenGenerator to the constructor.

public Startup(IConfiguration configuration, ITokenGenerator tokenGenerator)
{
    Configuration = configuration;
    TokenGenerator = tokenGenerator;
    string token = tokenGenerator.GetToken(); // do something with the token
}

private ITokenGenerator TokenGenerator { get; }
// snip

Then a simple call the TokenGenerator.GetToken() updates the header of the client the factory returns to callers.

For completeness, here is the implementation of the TokenGenerator.cs

public class TokenGenerator : ITokenGenerator
{
    private readonly IMemoryCache _memoryCache;
    public TokenGenerator(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }

    public string GetToken()
    {
        string token;
        if (_memoryCache.TryGetValue("Token", out token))
        {
            return token;
        }
        else
        {
            // here you would have a more realistic way of generating a new token
            token = Guid.NewGuid().ToString();
            _memoryCache.Set("Token", token, TimeSpan.FromSeconds(10));

            return token;
        }
    }
}

Full source code here.

Using Dependency Injection with Startup.cs in ASP.NET Core

Full source code available here.

Did you know that .NET Core 2 can pass in an instance of any type you want to the Startup.cs constructor? Well you can! Here’s how.

Out of the box the Startup.cs comes like this –

public class Startup
{
	public Startup(IConfiguration configuration)
	{
		Configuration = configuration;
	}
//snip..

The IConfiguration is passed in by dependency injection. In Program.cs you can add other types to the DI container, and then add that type to the constructor parameters of Startup.cs.

Here’s how it works. The Microsoft.AspNetCore.Hosting.WebHostBuilder has a ConfigureServices(...) method –

public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
{
    if (configureServices == null)
    {
        throw new ArgumentNullException(nameof(configureServices));
    }

    return ConfigureServices((_, services) => configureServices(services));
}

This lets you add services to the dependency injection container from the Program.cs.

WebHost.CreateDefaultBuilder(args) returns an IWebHostBuilder and that lets you use the ConfigureServices(...) method. Easy!

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureServices(serviceCollection =>
            serviceCollection.AddScoped<ISomeService, SomeService>())
        .UseStartup<Startup>()
        .Build();

And in Startup.cs

public class Startup
{
    private ISomeService _someService;
    public Startup(IConfiguration configuration, ISomeService someService)
    {
        _someService = someService;
        Configuration = configuration;
    }
// snip..	

The instance of ISomeService is of course available for DI everywhere in the application.

public class ValuesController : Controller
{
    private readonly ISomeService _someService;
    public ValuesController(ISomeService someService)
    {
        _someService = someService;
    }
}

Full source code available here.

Unit Testing a Method That Uses HttpClient

Full source code available here.

In this post I’m going to show you how test an action method of controller that uses a HttpClient. When performing this test you want to isolate just the code of the action method for testing, you want to remove the dependency on the HttpClient. I hoped it would be simple, that there would be an IHttpClient, but there is not.

Instead I mocked the HttpMessageHandler, then pass it to the constructor of the HttpClient. The HttpMessageHandler is set to return a list of numbers in response to any request.

The constructor of the controller takes the HttpClient as a parameter, usually passed by dependency injection.

public class ValuesController : Controller
{
    readonly IAsyncPolicy<HttpResponseMessage> _httpRetryPolicy;
    private readonly HttpClient _httpClient;

    public ValuesController(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
	//snip..

In the test class I mock the HttpMessageHandler, set its SendAsync method to return OK and a list of numbers in response to any request. I then pass the mocked HttpMessageHandler to the constructor of the HttpClient.

Now the HttpClient will return the list of numbers I expect and I my test just tests the code of the action method.

The rest of the test is written as normal.

[Fact]
public async Task GetTest()
{
    //Arrange
    string numberJson= JsonConvert.SerializeObject(new List<int>() { 1, 2, 3, 4, 5 });

    var httpMessageHandler = new Mock<HttpMessageHandler>();
    httpMessageHandler.Protected()
        .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
            ItExpr.IsAny<CancellationToken>())
        .Returns(Task.FromResult(new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent(numberJson, Encoding.UTF8, "application/json"),
        }));

    HttpClient httpClient = new HttpClient(httpMessageHandler.Object);
    httpClient.BaseAddress = new Uri(@"http://localhost:63781/v1/");
    httpClient.DefaultRequestHeaders.Accept.Clear();
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    ValuesController controller = new ValuesController(httpClient);

    //Act
    IActionResult result = await controller.Get();

    //Assert
    OkObjectResult resultObject = result as OkObjectResult;
    Assert.NotNull(resultObject);

    List<int> numbers = resultObject.Value as List<int>;
    Assert.Equal(5, numbers.Count);
}

Full source code available here.

Reusing HttpClient with Dependency Injection

Full source code available here.

If you are using HttpClient to make requests for you, you might have come across some articles discussing how to reuse HttpClient. They strongly advocate for using a single HttpClient for as many requests as possible, i.e. not creating a new HttpClient for every request.
Not having to create/dispose of the HttpClient for every request should improve the performance of you application. One estimate states that every time you instantiate a HttpClient takes 35ms.

In this article I will show you how to use dependency injection to reuse the HttpClient in .Net Core, but the same principle applies in Framework 4.x applications.

The one advantage of creating a new HttpClient for every request is that you don’t need to worry about the DNS record of an endpoint changing during the lifetime of the application, this is common if you are swapping staging and production instances during a deployment. But this is easyly(ish) handled by the ServicePointManger.

Adding HttpClient to the DI Container
In Startup.cs add the below lines.

public void ConfigureServices(IServiceCollection services)
{
    Uri endPointA = new Uri("http://localhost:58919/"); // this is the endpoint HttpClient will hit
    HttpClient httpClient = new HttpClient()
    {
        BaseAddress = endPointA,
    };

    ServicePointManager.FindServicePoint(endPointA).ConnectionLeaseTimeout = 60000; // sixty seconds

    services.AddSingleton<HttpClient>(httpClient); // note the singleton
    services.AddMvc();
}

This approach is ideal if you have a limited number of endpoints and you know them at application startup. If you don’t know then endpoints at startup you can add the call to ServicePointManager where you HttpClient requests occur.

Using the HttpClient
Now I have the HttpClient registered with the Dependency Injection container, let’s take a look at the controller that uses it to make a request. See the inline comments.

public class ValuesController : Controller
{
    private readonly HttpClient _httpClient; // declare a HttpClient

    public ValuesController(HttpClient httpClient) // this is the singelton instance of HttpClient
    {
        _httpClient = httpClient; // assign it to the local HttpClient
    }

    // GET api/values
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        string requestEndpoint = "api/products";

        HttpResponseMessage httpResponse = await _httpClient.GetAsync(requestEndpoint); // make request
        List<Product> products = await httpResponse.Content.ReasAsJsonAsync<List<Product>>();
        return Ok(products);
    }
}

Full source code available here.

Web API 2 and ninject, how to make them work together

Full source code to download.

I’ve been using ninject for a few years, but every time I use it with Web Api I hit some problem and they usually stem from not including the right nuget packages, not changing the DependencyResolver or (once) forgetting how to make a binding!

For my future self and your reference, here is how it is done.

1. Nuget packages

Add Ninject.Web.WebApi using nuget to your Web Api project.

That will install two other package dependencies:
Ninject
Ninject.Web.Common

To make everything work you need to add one more nuget package
Ninject.Web.Common.WebHost

This will pull down the WebActivatorEx package and add a new class called NinjectWebCommon to your App_Start directory.

2. Edit NinjectWebCommon.cs

NinjectWebCommon.cs is missing a key feature if you want to use ninject to construct the controllers, and I presume that is why you are using ninject inside a Web Api project.

In the CreateKernel() method add the second line shown below. Now ninject will be used to resolve controller dependencies.

RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;

You will need to add a couple of using statements too –

using System.Web.Http;
using Ninject.Web.WebApi;

3. Register some services

To actually register some services we move to the RegisterServices(..) method do some binding.

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<ICaclulator>().To<Caclulator>();
}

4. Use it all

And here is the usage in the controller.

    public class ValuesController : ApiController
    {
        private readonly ICaclulator _caclulator;
        public ValuesController(ICaclulator calculator)
        {
            _caclulator = calculator;
        }

        public int Get(int num1, int num2)
        {
            return _caclulator.Add(num1, num2);
        }
    }

Full source code to download.

CastleWindsor chained dependency

Source code is available here.

I recently had a problem where I wanted an MVC controller to use constructor injection of specified dependency and have that dependency load another specified dependency using Windsor.

For example, I have a message of the day controller and it can get messages from either a file or from a database. To support this I have a message of the day service which formats the text it retrieves from a message of the day loader.

But as I said I have two ways of loading the message, so for the sake of this demo I have two services and two loaders.

Controller, service and loader dependencies

Controller, service and loader dependencies

I don’t want my controller to request a named instance, I just want to register the implementations in the installers and let Windsor do the rest.

If the controller is using the database service, I want the database service to use the database loader; if the controller is using the file service, I want the file service to use the file loader.

To support this I added a ContractInstaller as shown here.

    public class ContractInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                 Component.For<IMessageLoader>().ImplementedBy<MessageLoaderDatabase>()
                ,Component.For<IMessageLoader>().ImplementedBy<MessageLoaderFile>()

                ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceDatabase>()
                    .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderDatabase>())

                ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceFile>()
                    .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderFile>())

                ,Component.For<MessageOfTheDayController>().LifestyleTransient()
                    .DependsOn(Dependency.OnComponent<IMessageOfTheDayService, MessageOfTheDayServiceFile>())
            );
        }
    }

In lines 6 and 7 I register the loaders (IMessageLoader), and in lines 9 and 12 I register the the services (IMessageOfTheDayService) and they in turn depend on the registered loaders.
In line 15 I register the controller (MessageOfTheDayController) and its dependency on IMessageOfTheDayService, in this case it is using MessageOfTheDayServiceFile.
To use the MessageOfTheDayServiceDatabase, change the dependency on line 16.

Be sure to load this before the ControllersInstaller provided by the Windsor nuget or you will get a clash between the MessageOfTheDayController loaded by both installers. To make sure this happens I alter the default Bootstrap method in ContainerBootstrapper to the following.

        public static ContainerBootstrapper Bootstrap()
        {
            var container = new WindsorContainer().Install(
                new ContractInstaller(),
                new ControllersInstaller()
                );

            return new ContainerBootstrapper(container);
        }

Now when you run the app, the controller will be instantiated with the MessageOfTheDayServiceDatabase which in turn will be instantiated with MessageLoaderDatabase.