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.

How to Turn Off Console Logging for Kestrel in .NET Core

This post is mostly a note to myself.

I am often annoyed with the amount of logging to the console that occurs when I start a Kestrel hosted application and I can never remember how to turn it off.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .ConfigureLogging(loggingBuilder => 
        loggingBuilder.AddFilter<ConsoleLoggerProvider>(level => 
            level == LogLevel.None))
        .UseStartup<Startup>();

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.

Caching in Polly 6 and the HttpClientFactory

Full source code here.

Polly allows you to cache a response for reuse by a subsequent request, it supports both local an distributed caches, full information can be found here https://github.com/App-vNext/Polly/wiki/Cache.

The HttpClientFactory lets you define polices in startup.cs and apply them to HttpClient requests anywhere in your application. With most policies this makes it easier for you to apply a policy to a request, but with the cache policy it complicates matters.

With the release of HttpClientFactory there are now two ways to use the cache policy, one taking advantage of HttpClientFactory to apply the policy to requests, and the other bypassing it when executing requests.

Caching with the cache policy inside the HttpClientFactory
First let’s look at how to use the Cache Policy using PolicySelector method on the HttpClientFactory to apply the policy to the request, see this post for more info.

If you are working in Polly V6+ add Polly.Caching.Memory package to your project, this is important, don’t add Polly.Caching.MemoryCache that is for Polly V5.9 and earlier, and many an hour was lost figuring that out.

In Startup.cs add the following to the ConfigureServices method –

public void ConfigureServices(IServiceCollection services)
{
    services.AddMemoryCache();
    services.AddSingleton<IAsyncCacheProvider, MemoryCacheProvider>();

    IPolicyRegistry<string> registry = services.AddPolicyRegistry();

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

This sets up the in memory cache and policy registry, adding both to ServicesCollection. The cache policy is not added here, instead it is added in the Configure(..) method (thanks Andrew Lock for reminding me about this).

Next, add the HttpClientFactory and a method to pick the appropriate policy from the registry.

Inside the Configure(..) I setup the cache policy. The registry and cache provider are passed via dependency injection.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
    IAsyncCacheProvider cacheProvider, IPolicyRegistry<string> registry)
{
    CachePolicy<HttpResponseMessage> cachePolicy = 
        Policy.CacheAsync<HttpResponseMessage>(cacheProvider, TimeSpan.FromSeconds(30));
    registry.Add("CachingPolicy", cachePolicy);

In the controller I have a constructor that takes one argument, the HttpClientFactory.

public CatalogController(IHttpClientFactory httpClientFactory)
{
    _httpClientFactory = httpClientFactory;
}

In the action method I get the HttpClient from the HttpClientFactory and specify the remote endpoint I want to call, but now I can’t use usual httpClient.GetAsync(..) because I can’t pass it an cache context key (i.e. the name of where I look for previously cached responses and store new responses).
Instead I build a HttpRequestMessage, specifying the HttpMethod, Uri and using Polly extension method I set the cache context.

HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, 
    new System.Uri(httpClient.BaseAddress + requestEndpoint));

httpRequestMessage.SetPolicyExecutionContext(new Context($"GetInventoryById-{id}"));

HttpResponseMessage response = await httpClient.SendAsync(httpRequestMessage);

This approach feels a bit awkward and not many people use the HttpRequestMessage to send requests to remote services. T

Caching with the cache policy outside the HttpClientFactory
An alternative to the above is to add the cache to the registry, but not add the registry to the HttpClientFactory.

In this case the adding the HttpClientFactory to the services collection changes slightly –

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

In the controller we now pass in the registry as HttpClientFactory as constructor arguments.

public StockMgtController(IHttpClientFactory httpClientFactory, IPolicyRegistry<string> policyRegistry) 
{
    _httpClientFactory = httpClientFactory;
    _policyRegistry = policyRegistry;
}

There are changes inside the action method also –

[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
    string requestEndpoint = $"inventory/{id}";
    var httpClient = _httpClientFactory.CreateClient("RemoteServer");

    var cachePolicy = _policyRegistry.Get<CachePolicy<HttpResponseMessage>>("CachingPolicy");
    Context policyExecutionContext = new Context($"GetInventoryById-{id}");

    HttpResponseMessage response = await cachePolicy.ExecuteAsync(
        context => httpClient.GetAsync(requestEndpoint), policyExecutionContext);
	//snip..	

The httpClient is retrieved from the HttpClientFactory as before, but now the cachePolicy is taken from the policy registry, the Context is defined and then we use the cachePolicy.ExecuteAsync(..) method to make call the httpClient.GetAsync(..) method.

The other way
You might have noticed that there is another way of using the cache policy. You could use the HttpClientFactory and a PolicySelector method to apply most policies to your HttpClient requests, but not for the cache policy. I wouldn’t do this, it will confuse everyone.

Conclusion
The outcome of both is the same, I think the first approach is better, even though the call to the httpClient is a little more convoluted, it will be more consistent with how you call other policies in your application, there is also a chance the Polly team will add an extension method to make the use of HttpRequestMessage transparent to us developers.

Full source code here.

Using Polly with Any Type of Request

Full source code here.

I recently presented a talk on Polly at the DevUp conference in St. Louis. In the presentation I showed examples using Polly with HttpClient requests only because this is my most common use case. I showed how to use retries, circuit breakers, fallbacks, caching, timeouts and bulkheads isolation. At the end of the presentation a few people asked me if Polly could be used with other types of request, of course it can and I should have said so during the talk. I’ve added new slide for the next time I present on Polly – (as of October 2018 that will be Granite State Code Camp, Boston Code Camp and NDC London).

Polly can be used with any type of request you make, whether it returns a value or not. You can use on code that throws exceptions from time to time (though I strongly recommend fixing your code), for database calls, any method call for that matter. Below are some examples of using the retry policy in a variety of scenarios.

Exceptions
This policy retries if an exception is thrown, you can be more specific about exception types.

 
RetryPolicy retryIfException = Policy.Handle<Exception>()
    .Retry(4, (exception, retryCount) =>
    {
        Console.WriteLine($"Got a response of {exception.Message} (expected 0), retrying {retryCount}");
    });

Int
Here I check check if the int returned is anything other than 0, or if there has been a DivideByZeroException. If so, I retry up to four times and also print some text to console.

 
RetryPolicy<int> retryPolicyNeedsAResponseOfOne = Policy.HandleResult<int>(i => i != 0)
    .Or<DivideByZeroException>()
    .Retry(4, (response, retryCount) =>
    {
        Console.WriteLine($"Got a response of {response.Result} (expected 0), retrying {retryCount}");
    });

IEnumerable
In this one I check that the IEnumerable has three items in it, if not, I retry and print some info to the console.

 
RetryPolicy<IEnumerable<int>> retryPolicyNeedsResponeWithTwoNumbers = Policy.HandleResult<IEnumerable<int>>(l => l.Count() != 3)
   .Retry(4, (response, retryCount) =>
   {
       Console.WriteLine($"Got a reponse with {response.Result.Count()} entries (expected 3), retrying {retryCount}");
   });

Bool
In this policy I check the bool returned, if it is false, I retry.

 
RetryPolicy<bool> retryPolicyNeedsTrueResponse = Policy.HandleResult<bool>(b => b != true)
   .Retry(4, (response, retryCount) =>
   {
       Console.WriteLine($"Got a reponse of {response.Result} entries (expected true), retrying {retryCount}");
   });

Polly can check the value of any return type or exception making it possible to use Polly for any call you can think of.

Full source code here.

Saving Enums with Entity Framework Core

Full source code here.

A few years ago I wrote a post about saving enums to the database with Entity Framework. It was able to save the enum as a string to the database and when reading from the database it was able to take that string and populate the enum correctly. It worked fine but felt a bit hacky.

With Entity Framework Core there is a neater and nicer way to do this using value conversions.

Let’s say we have an Address with two enums – AddressType and DeliveryPreference.

public partial class Address
{
    public int AddressId { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public AddressType AddressType { get; set; }
    public DeliveryPreference DeliveryPreference { get; set; }
}

We can save the enums to the database as either strings or ints, and when reading them back populate the enum! Here’s how to do both.

The table
My table looks like this

As you can see, the AddressType is stored as an int and the DeliveryPreference is stored as a string.

When you run the application it should create the database and table for you, but in case you don’t have your permissions setup correctly, here’s the script to create it.

CREATE TABLE [dbo].[Address] (
    [AddressId]          INT            IDENTITY (1, 1) NOT NULL,
    [Line1]              VARCHAR (50)   NOT NULL,
    [Line2]              VARCHAR (50)   NOT NULL,
    [AddressType]        INT            NOT NULL,
    [DeliveryPreference] VARCHAR (50) NOT NULL,
    CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ([AddressId] ASC)
);

Saving an enum as an string
Firstly lets look at saving the DeliveryPreference enum as an string.

In the context we build the entity, I have the usual things you would expect for AddressId, Line1 and Line2. But DeliveryPreference is a little different.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Address>(entity =>
    {
        entity.Property(e => e.AddressId).ValueGeneratedOnAdd();

        entity.Property(e => e.Line1)
            .IsRequired()
            .HasMaxLength(50)
            .IsUnicode(false);

        entity.Property(e => e.Line2)
            .IsRequired()
            .HasMaxLength(50)
            .IsUnicode(false);

        entity.Property(e => e.DeliveryPreference) 
            .HasMaxLength(50)
            .HasConversion(x => x.ToString(), // to converter
                x => (DeliveryPreference) Enum.Parse(typeof(DeliveryPreference), x));// from converter

	    //snip..

The DeliveryPreference uses the HasConversion method, passing it two parameters.
The first parameter is the convert to provider expression which as the name suggests converts the value in our object to the type you will store in the database.

And the second is the convert from provider expression, it converts the the type in database to the type in your class.

In this example, I cast the enum to an string to store in the database, and when retrieving from the database I cast the stored string to an DeliveryPreference enum.

Saving an enum as an int
For the second enum, AddressType I don’t explicitly need to convert it from an enum to an int, Entity Framework will do this automatically (as pointed out to me in this tweet). But I’m including it as an example in case you need something like this for some other explicit conversion.

In this example, I cast the enum to an int to store in the database, and when retrieving from the database I cast the stored int to an AddressType enum.

// this is a continuation of the OnModelCreating method
        entity.Property(e => e.AddressType)
            .HasConversion(x => (int) x, x => (AddressType) x);

Full source code here.

Performance Comparison of Entity Framework Core 2.1 and Dapper 1.5

tl;dr – ignore most (maybe all) of the posts out there comparing Dapper and Entity Framework performance, you need to measure it yourself.
Here’ why –
1. Some are angry opinion pieces from people who don’t like one technology or the other and clearly haven’t run any tests.
2. All are out of date (as this one will be shortly) because the libraries move so quickly.
3. None are running against the database and network you have.
4. Your standard queries are far more important than whatever arbitrary queries they used.

Longer Version
I recently had to decide between a few different ORMs for a project, the specifics of the project are irrelevant, but I was using a Postgres database that had lots of data (my lots and your lots are probably different, that I had hundreds of millions of records should not matter to you).

Most of the posts comparing Dapper and EF that I read came down on the side of Dapper, some by a tiny margin and one by no margin but a lot of bluster.

Rather than trust any of these posts I wrote my own benchmarking application using the BenchmarkDotNet library.

I picked seven of the most representative queries I was making and coded them up in both Dapper and EF. Some of the queries pulled back tens of thousands of records and some brought back scores of records, but the most important thing was that these were queries I was going to run in the finished application.

BenchmarkDotNet takes care of things making sure the code has been jitted, that everything has been “warmed up” and then it runs the same request repeatedly to get a useful average.

On top of this, I ran the whole suite of benchmarking tests multiple time, at different times of the day because my application does not live in a vacuum, I needed to know how it would react when the network or database is under more or less load.

At the end of all this Entity Framework came out on top; for the vast majority of test runs it performed better.

Here are the results of one of the test runs, I didn’t pick the best or the worst, but this one is is indicative of what I saw for the majority of tests.

MethodMeanErrorStdDevMedian 
EF_Query1431.19 ms 13.9615 ms38.1581 ms 445.98 ms
Dapper_Query1689.88 ms 35.9716 ms102.7689 ms668.13 ms
EF_Query245.21 ms 1.5613 ms4.6816 ms46.35 ms
Dapper_Query261.55 ms1.7915 ms5.0850 ms62.19 ms
EF_Query3278.72 ms 51.4681 ms150.8833 ms351.38 ms
Dapper_Query3298.64 ms7.3619 ms20.2561 ms297.15 ms
EF_Query417.97 ms 0.3570 ms0.6310 ms17.93 ms
Dapper_Query426.59 ms 0.6516 ms1.7592 ms25.78 ms
EF_Query570.78 ms 1.4936 ms4.0985 ms71.21 ms
Dapper_Query5116.71 ms2.5632 ms7.4015 ms116.36 ms
EF_Query6189.71 ms50.1289 ms148.7825 ms311.21 ms
Dapper_Query6248.61 ms7.2891 ms21.1751 ms304.16 ms
EF_Query7266.62 ms6.2219 20.3179 ms281.27 ms
Dapper_Query7304.27 ms7.8163 ms15.1561 ms301.21 ms

I was a little surprised at this result, but there you have it. EF Core 2.1 is better for me than Dapper.

Out of interest, I took a small portion of my data and put it into SqlServer, and re-ran the tests. This time, Dapper came out slightly ahead. But the SqlServer is on a different network than the Postgres db, is under different load and had a much small dataset so not a realistic exercise.

Conclusion
The moral of the story is you have to test performance yourself, there is absolutely no way you can extrapolate from a test someone wrote about in a blog (including this one) when judging how an ORM will perform for you.

Alter response header in Web API to return machine name

Full source code available here.

I recently hit a problem where I was getting incorrect responses from a server behind a load balancer. Looking at the logs didn’t help because there was no error.

It was likely due to a misconfigured environmental variable but I couldn’t even identify which server was having the problem because of the load balancer.

Luckily the application was a .NET Core Web Api and I could use a little bit of middleware to add the server name to the response header.

It’s a trivial change in the Configure(..) method of Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Use((context, next) =>
    {
        context.Response.Headers.Add("MachineName", $"{Environment.MachineName}");
        return next();
    });
    app.UseMvc();
}

That’s all I had to do.

Here’s how the response looks now.

.

Full source code available here.