Streaming Results from Entity Framework Core and Web API Core

Full source code here.
The code provided will not compile until you make a change in seeder.cs, the way it’s written it generates 500,000 rows in a local db. Set this to whatever value you want.

In this post I’m going to show you how to return an unlimited number of results from a database via a Web API application while keeping your memory usage low and constant. In effect, you are going to stream results from the database with Entity Framework.

To achieve this you need to do two things, disable tracking and return a not materialize your data inside the action method.

Turn off tracking
By default Entity Framework tracks entities that you read from a database. Tracking allows EF to determine what, if any, properties have changed since being loaded, then EF can save just the relevant changes. But tracking takes up memory and CPU.

If you have no intention of changing these entities there is no point in tracking them.

There are two ways of doing this, at point where you make the request to the database, or globally for the whole context.

To use AsNoTracking for a single request it looks like this –
_salesContext.Products.AsNoTracking().Where(..)

To use it for all requests to that context set AsNoTracking in the constructor of the context.

public SalesContext(DbContextOptions<SalesContext> options) : base(options)
{
	ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}

That’s the first step taken care of, now we make sure not to turn our data into objects inside the controller.

Do not materialize
If you follow tutorials on Entity Framework Core and Web API you will see examples like this –

[HttpGet]
public async Task<ActionResult> Get()
{
    List<Product> products = await _salesContext.Products.ToListAsync();

    return Ok(products);
}

In this example, all the products in the database are read and put into a list of products, the return does not execute until after all the data has been read, so you are waiting for this to complete before getting any results. You are also storing the whole list of products in memory (you are probably also tracking the entities).

Instead of that you can do the following –

[HttpGet]
public ActionResult GetStreaming()
{
	IQueryable<Product> products = _salesContext.Products.AsNoTracking();

	return Ok(products);
}

Now, the products do not materialize, there is no list to store in memory, tracking is turned off and the action method begins returning data almost immediately.

Your memory profile will be almost same whether you are returning a few hundred or a few million rows of data.

Example of Memory Usage
Below are screenshots from Visual Studio 2017 of the application running showing the amount of memory consumed for a variety of requests. The first shows the memory usage when I requested a single row from the database

The following images show the memory usage when streaming and not streaming results sets of 100,000, 200,000, 300,000 and 500,000.

106 MB used for a single row

 

100,000 rows returned. On the left is with streaming, on the right without.

 

200,000 rows returned. On the left is with streaming, on the right without.

 

300,000 rows returned. On the left is with streaming, on the right without.

 

500,000 rows returned. On the left is with streaming, on the right without.

 

Summary of Results

It’s obvious that streaming maintains a uniform memory footprint while the memory consumed for non-streaming grows with the number of rows returned.

What you don’t see here is that streaming requests complete more quickly. If you download the attached code and use a local mdf file, you probably won’t see much of a difference in speed, but if your application connects to remote database you will see approximately a 20% improvement in speed.

Summary
For streaming to work you need to turn of tracking of entities and return an IQueryable from the action method.

Full source code here.
The code provided will not compile until you make a change in seeder.cs, the way it’s written it generates 500,000 rows in a local db. Set this to whatever value you want.

Getting Error Messages and Status Codes from Typed HttpClients

Full source code here.

I have been using HttpClientFactory for a while and have generally preferred using named clients over typed clients. With a named client you get the HttpClient just before you are going to use it, and you have full access to the HttpResponse at the point you make the call to the remote service.

var httpClient = _httpClientFactory.CreateClient("InvoiceApi");
HttpResponseMessage response = await httpClient.GetAsync(requestEndpoint);

This is great when things go wrong because you can check the HttpStatus code and the ReasonPhrase, any message, and then take appropriate action.

If you are using a typed client, it might look something like this –

public class InvoiceClient
{
	private readonly HttpClient _client;

	public InvoiceClient(HttpClient client)
	{
		_client = client;
	}
	
	public async Task<Invoice> GetInvoice(int orderId)
	{
		var response = await _client.GetAsync($"invoice/{orderId}");
		Invoice invoice = await response.Content.ReadAsAsync<Invoice>();
		return invoice;
	}
}

And then you use it –

var invoice = await invoiceClient.GetOrder(id);

If the request worked, you are fine, but if it didn’t you and got an error, then the deseriaization will fail and an exception will be thrown, but that exception won’t tell you very much about the cause of the original failure.

Returning a typed response
Here’s the alternative. I use a typed response that includes the HttpStatusCode, the ReasonPhrase and the content I actually want, in this case the Invoice.

public class TypedResponse<T>
{
	public T Content { get; set; }
	public HttpStatusCode HttpStatusCode { get; set; }
	public string ReasonPhrase { get; set; }
	public string Message { get; set; }
}

Here’s how to change the Get method in the Invoice.

[HttpGet("{orderId}")]
public async Task<ActionResult> Get(int orderId)
{
	// Pretend to load the order from the db. 
	Order order = new Order { OrderId = orderId, OrderDate = new DateTime(2018, 6, 14), CustomerId = 1001 };

	var invoiceResponse = await _invoiceClient.GetInvoice(orderId);

	if (invoiceResponse.Content != null)
	{
		order.Cost = invoiceResponse.Content.Cost;
		return Ok(order);
	}
	return StatusCode((int)invoiceResponse.HttpStatusCode, invoiceResponse.Message);
}

And finally, how to use it in the controller.

var invoiceAndStatus = await _invoiceClient.GetInvoice(orderId);

if (invoiceAndStatus.Content != null)
{
    order.Cost = invoiceAndStatus.Content.Cost;
    return Ok(order);
}
return StatusCode((int)invoiceAndStatus.HttpStatusCode, invoiceAndStatus.Message);

Run the code, it will open your browser to http://localhost:5000/api/order/2. The OrderController will call the InvoiceController, the first request will fail, but you will see the error message from the InvoiceController.

Hit F5 in the browser to make another request to the OrderController, again this calls the InvoiceController, but this time the response is a success.

Full source code here.

Selectively Caching Values Inside HttpResponseMessage with Polly – caching series 3/3

Full source code here.

This is the last of three posts on caching with Polly. The first showed how to selectively cache HttpResponseMessages based on the status code of the response.

The second showed how to cache values inside the HttpResponseMessage rather than the whole of the response.

This final post will show how to selectively cache values inside the response based on the status of the response.

If you have read the previous posts the content of this will feel familiar.

Changes to Startup
Like the previous post, add a memory cache, a policy registry and a HttpClientFactory to the service collection.

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");
    });

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

What’s new is in the Configure method, fist step is to add the registry to the method parameters, DI will take care of this for us.

public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    IAsyncCacheProvider cacheProvider, IPolicyRegistry<string> registry)
{

Next is the cache filter, this one examines the tuple of int and HttpStatusCode and, if the HttpStatusCode is an OK the tuple will be cached for the duration specified. If the respones is not OK the filter will set the cache time to 0 which is interpreted as do not cache by the cache policy.

Func<Context, (int value, HttpStatusCode StatusCode), Ttl> cacheOnly200OkFilter =
	(context, result) => new Ttl(
		timeSpan: result.StatusCode == HttpStatusCode.OK ? TimeSpan.FromSeconds(5) : TimeSpan.Zero,
		slidingExpiration: true
	);

And this is the cache policy that uses the filter above to store the tuple.

IAsyncPolicy<(int, HttpStatusCode)> cachePolicy =
	Policy.CacheAsync<(int, HttpStatusCode)>(
		cacheProvider.AsyncFor<(int, HttpStatusCode)>(), 
		new ResultTtl<(int, HttpStatusCode)>(cacheOnly200OkFilter),
		onCacheError: null);

Lastly, add the policy to the registry.

registry.Add("cacheOnly200OkFilter", cachePolicy);

Changes to the Controller
Over in the CatalogController there many changes.

At the top I take in the HttpClientFactory and policy registry.

private readonly IHttpClientFactory _httpClientFactory;
private readonly IPolicyRegistry<string> _policyRegistry;

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

Inside the Get method, I setup grab the HttpClient from the HttpClientFactory, set the endpoint of the remote service, take the cache policy from the registry and setup the context for the cache policy to cache based on the incoming request. All of this is similar to normal usage of the Polly cache.

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

    var cachePolicy = _policyRegistry.Get<CachePolicy<(int, HttpStatusCode)>>("cacheOnly200Ok");
    Context policyExecutionContext = new Context($"GetInventoryById-{id}");	

As in the previous post I don’t call the HttpClient from inside the cache policy, instead I need to call something that returns the int and the HttpStatusCode. I use a local function that makes the request to the remote service, checks the response, deserializes the value and returns a tuple.

(int ItemsInStock, HttpStatusCode StatusCode) itemsInStockAndStatusCode =
    await cachePolicy.ExecuteAsync(context => MakeRequest(), policyExecutionContext);

// local function
async Task<(int count, HttpStatusCode statusCode)> MakeRequest()
{
    HttpResponseMessage response = await httpClient.GetAsync(requestEndpoint);

    if (response.IsSuccessStatusCode)
    {
        int itemsInStock = JsonConvert.DeserializeObject<int>(await response.Content.ReadAsStringAsync());
        return (itemsInStock, response.StatusCode);
    }

    return (0, response.StatusCode);
}

When the cachePolicy is executed it first checks if there is value already in the cache, if there is, that will be returned and the local function will not be called. If there is no value in the cache, the local function is called, if the response of the local function is in the 200 range, the value is stored in the cache.

At this point, the action method has not returned anything to its caller.

Below the local function I check the tuple returned from the call to the cache policy and return a response.

if (itemsInStockAndStatusCode.StatusCode != HttpStatusCode.OK)
{
     return StatusCode((int)itemsInStockAndStatusCode.StatusCode);
}
return Ok(itemsInStockAndStatusCode.ItemsInStock);

For clarity, here is the full Get method.

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

    var cachePolicy = _policyRegistry.Get<CachePolicy<(int, HttpStatusCode)>>("cacheOnly200Ok");
    Context policyExecutionContext = new Context($"GetInventoryById-{id}");

    (int ItemsInStock, HttpStatusCode StatusCode) itemsInStockAndStatusCode =
        await cachePolicy.ExecuteAsync(context => MakeRequest(), policyExecutionContext);

    async Task<(int count, HttpStatusCode statusCode)> MakeRequest()
    {
        HttpResponseMessage response = await httpClient.GetAsync(requestEndpoint);

        if (response.IsSuccessStatusCode)
        {
            int itemsInStock = JsonConvert.DeserializeObject<int>(await response.Content.ReadAsSt
            return (itemsInStock, response.StatusCode);
        }

        // it doesn't matter what int you use here, it won't be cached as the StatusCode is not a
        return (0, response.StatusCode);
    }

    if (itemsInStockAndStatusCode.StatusCode != HttpStatusCode.OK)
    {
         return StatusCode((int)itemsInStockAndStatusCode.StatusCode);
    }
    return Ok(itemsInStockAndStatusCode.ItemsInStock);
}

Here endeth the series on caching.

Full source code here.

Caching Values Inside HttpResponseMessage with Polly – caching series 2/3

Full source code here.

In this, the second of three posts on caching in Polly, I will show how to cache the values returned inside a HttpResponseMessage as opposed to caching the response with all its various elements.

The first post explained how to selectively cache a response, based on the Http StatusCode. The next post will show how to combine these two ideas and selectively cache the values inside the HttpResponseMessage.

Caching the whole response or the value
Caching the whole HttpResponseMessage is useful if your business logic depends on interrogating the response for values outside the main payload or you want a quick and easy caching solution.

If on the other hand, you only need the payload, there is no need to cache the whole response.

Both cases are plausible, and it is up to do decide which is more appropriate for your application.

How to cache the value inside HttpResponseMessage
The first step is to set the cache inside ConfigureServices.

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

Then in Configure, setup the policy to store the type you expect to find in the response. In this example it is in a int, but it could easily be a complex layered model representing anything.

public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    IAsyncCacheProvider cacheProvider, IPolicyRegistry<string> registry)
{
    CachePolicy<int> cachePolicy =
        Policy.CacheAsync<int>(cacheProvider, TimeSpan.FromSeconds(10));

    registry.Add("CachingPolicy", cachePolicy);

Note, how I specified an int rather than a HttpResponseMessage.

In the previous post, I used the HttpClientFactory to select the policy from a Polly policy registry. I could do that because the type I was storing was HttpResponseMessage, that is not the case now and HttpClientFactory will not play nice when trying to cache anything other than a HttpResponseMessage. Instead I’m going to pass the policy registry directly to the controller and get the policy from this, I am still using the HttpClientFactory to pass HttpClient, but not for policy selection.

Here is how the controller starts.

public class CatalogController : Controller
{
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly IPolicyRegistry<string> _policyRegistry;

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

And here is the GET method.

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

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

    int itemsInStock =
        await cachePolicy.ExecuteAsync(context => GetItemsInStockCount(), policyExecutionContext);

    async Task<int> GetItemsInStockCount()
    {
        HttpResponseMessage response = await httpClient.GetAsync(requestEndpoint);

        if (response.IsSuccessStatusCode)
        {
            int itemsInStockCount = await response.Content.ReadAsAsync<int>();
            return itemsInStockCount;
        }

        return 0;
    }

    return Ok(itemsInStock);
}

The first few lines are straight forward, setup the endpoint, get the HttpClient, get the cache policy. Like in the previous post, I use the context when placing items into the cache and retrieving them.

Because I want to cache the value inside the HttpResponse (and not the response itself) I can’t call the HttpClient from inside the policy’s exec method. Instead I need to call something that returns the int from inside the HttpResponse.

The easiest way of doing this is to use a local function which makes the HttpClient request, deserializes the response and returns the int from the response.
In this post I am assuming that all values inside the response should be cached, I am NOT checking the status code of the response.

The policy then caches the int for the period specified in Startup.

That’s all there is to it.

If you are wondering how to selectively cache values inside the HttpResponse, tune in for the next post in this series.

Full source code here.

Selectively Caching a HttpResponseMessage with Polly – caching series 1/3

Full source code here.

When I give talks on Polly I show how to use it in a Web API application that calls another Web Api application. I give a simple example of how to use the cache policy where I store the whole of the HttpResponseMessage. At the end of the talk I often get a couple of questions –

1. is it possible to cache the response only when the status code is in the 200 range.
2. is it possible to cache the values inside the response instead of the whole response.

The answer to both of these is yes, and in this series of three articles I will explain how to do both of these things, and how how to combine them to cache a value inside a response only if the response is in the 200 range.

This article will demonstrate how to selectively cache HttpResponseMessages based on the Http StatusCode of the response.

As described in an earlier post, using a cache policy is a little more involved than using other policies. See this post for more info.

Changes in Startup
In Startup inside ConfigureServices I setup the memory cache, the HttpClientFactory and a policy registry (I’m not going to go into a detailed explanation of this code as it is already explained in the earlier article and you have all the source code).

All the action for this post takes place in the Configure method.

Creating the cache filter
The cache timeout filter, it sets the length of time to cache a value. The filter here will cache a response for 10 seconds if the response indicates a success, otherwise it caches the response for 0 seconds, in this case the Polly code does not perform any caching.

public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    IAsyncCacheProvider cacheProvider, IPolicyRegistry<string> registry)
{
    Func<Context, HttpResponseMessage, Ttl> cacheOnly200OkFilter =
        (context, result) => new Ttl(
            timeSpan: result.StatusCode == HttpStatusCode.OK ? TimeSpan.
            slidingExpiration: true
        );

The cache policy says that it caches HttpResponseMessages and uses the filter to decide if a response should be cached.

IAsyncPolicy<HttpResponseMessage> cacheOnlyOkResponsePolicy =
    Policy.CacheAsync<HttpResponseMessage>(
        cacheProvider.AsyncFor<HttpResponseMessage>(), //note the .AsyncFor<HttpResponseMessage>
        new ResultTtl<HttpResponseMessage>(cacheOnly200OkFilter),
        onCacheError: null
    );

Note the AsyncFor, this is very important. Thanks to Dylan Reisenberger for his help here, I spent too many hours trying to figure the overloads with no success.

Try it out in the provided solution, hit F5 and put some breakpoints in the controllers and on the filter in Startup.

That’s it, you now have selective caching of responses.

In the next post, I’ll show you how to cache the value inside the response instead of the whole response.

Full source code here.

Testing Your Code When Using Polly

Full source code here.

When developing an application with Polly you will also probably want to write some unit tests.

Here are the scenarios I test for –

1. How my code behaves when the policy throws an exception, such as TimeoutRejectionException, BulkheadRejectedException or BrokenCircuitException.
2. How my code behaves when a policy becomes active and changes the outcome of a call, such as when an unreliable request works because Polly performs a retry.
3. What my code should do if there was no policy in place.

I have a few classes to demonstrate these scenarios, BusinessLogic.cs and OtherBusinessLogic.cs are the classes under test. ErrorProneCode.cs is the unreliable class that I will mock and pass mocked policies into.

For the first case I use Moq to mock the error prone code so it returns an incorrect value.

[Fact]
public void Should_Return_999_When_TimeoutRejectedException_Thrown()
{
    //Arrange 
    Mock<IErrorProneCode> mockedErrorProneCode = new Mock<IErrorProneCode>();
    mockedErrorProneCode.Setup(e => e.GetSomeNumber()).Returns(0);

    Mock<ISyncPolicy> mockedPolicy = new Mock<ISyncPolicy>();
    mockedPolicy.Setup(p => p.Execute(It.IsAny<Func<int>>())).Throws(new TimeoutRejectedException("Mocked Timeout Exception"));

    IBusinessLogic businessLogic = new BusinessLogic(mockedPolicy.Object, mockedErrorProneCode.Object);

    //Act
    // if there is a TimeoutRejectedException in this CallSomeSlowBadCode it will return 999
    int num = businessLogic.CallSomeSlowBadCode();

    //Assert
    Assert.Equal(999, num);
}

In the next case I verify that the application has correctly used the retry policy method. I use a seeded random number generator that produces an known sequence to return values from the ErrorProneCode class.

  
[Fact]
public void Should_Return_Odd_When_Retry()
{
    //Arrange 
    Mock<IErrorProneCode> mockedErrorProneCode = new Mock<IErrorProneCode>();

    Random rnd = new Random(1); // rnd.Next(10) retruns 2, 1, 4 

    mockedErrorProneCode.Setup(e => e.GetSomeNumber()).Returns(() => rnd.Next(10));

    ISyncPolicy<int> policy = Policy.HandleResult<int>(i => i %2 !=1) // retry if the number is not odd.
        .Retry(1);
    OtherBusinessLogic otherBusinessLogic = new OtherBusinessLogic(policy, mockedErrorProneCode.Object);

    //Act
    int num = otherBusinessLogic.CallSomeCodeThatNeedsToBeRetried();

    //Assert
    Assert.Equal(1, num % 2);
}

Finally, I want to verify that my code will work if no Polly policy is in use. To do this, I pass in a NoOp policy.

[Fact]
public void Should_Return_Even_With_NoOp()
{
    //Arrange 
    Mock<IErrorProneCode> mockedErrorProneCode = new Mock<IErrorProneCode>();

    Random rnd = new Random(1); // rnd.Next(10) retruns 2, 1, 4 

    mockedErrorProneCode.Setup(e => e.GetSomeNumber()).Returns(() => rnd.Next(10));

    ISyncPolicy<int> policy = Policy.NoOp<int>();
    OtherBusinessLogic otherBusinessLogic = new OtherBusinessLogic(policy, mockedErrorProneCode.Object);

    //Act
    int num = otherBusinessLogic.CallSomeCodeThatNeedsToBeRetried();

    //Assert
    Assert.Equal(0, num % 2); //even number
}

Full source code here.

Calling Generic Methods Using Reflection

Full source code here.

Accessing generic methods by reflection is not easy. A while ago I needed to do just that and found relatively little information out there. So I dug in a figured it out for myself.

Here are some of the possible ways that you could execute generic methods by reflection –

  • Execute a Generic Instance Method in a Non-Generic Class
  • Execute Generic Static Method In a Non-Generic Class
  • Execute Generic Overloaded Static Method
  • Execute NonGeneric Method in a Generic Class

There are other variations, but you should be able to figure out how to write them based on the ones shown here.

In the classes PrinterA and PrinterB, there are a variety of generic and one non-generic methods that I will call using reflection from Program.

The code will explain things better than I can, so here is the listing.

using System;
using System.Collections.Generic;

namespace ExecuteGenericMethodByReflection
{
    public class PrinterA<T>
    {
        public void Print(IEnumerable<T> items)
        {
            Console.WriteLine();
            foreach (var item in items)
            {
                Console.Write($"{item} ");
            }
        }
    }
}
using System;
using System.Collections.Generic;

namespace ExecuteGenericMethodByReflection
{
    public class PrinterB
    {
        public void PrintSimple<T>(IEnumerable<T> items)
        {
            Console.WriteLine();

            foreach (var item in items)
            {
                Console.Write($"{item} ");
            }
            Console.WriteLine();

        }

        public static void PrintPrefixAndSuffix<T>(IEnumerable<T> items, string prefix, string suffix)
        {
            Console.Write(prefix);
            foreach (var item in items)
            {
                Console.Write($" {item} ");
            }
            Console.Write(suffix);
            Console.WriteLine();
        }

        //This and the next method are overloads
        public static void PrintPrefix<T>(IEnumerable<T> items, string prefix)
        {
            Console.Write(prefix);

            foreach (var item in items)
            {
                Console.Write($" {item}");
            }
            Console.WriteLine();

        }

        public static void PrintPrefix<T>(IEnumerable<T> items, int prefix)
        {
            Console.WriteLine(prefix);

            foreach (var item in items)
            {
                Console.Write($" {item}");
            }
            Console.WriteLine();
        }

    }
}

And here is program where all the crazy reflection takes place.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace ExecuteGenericMethodByReflection
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();

            List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };

            p.ExecuteGenericInstanceMethodInNonGenericClass(numbers);
            p.ExecuteGenericStaticMethodInNonGenericClass(numbers);
            p.ExecuteGenericOverloadedStaticMethod(numbers);

            p.ExecuteNonGenericMethodInGenericClass(numbers);

            Console.WriteLine("\n\nPress any key to exit...");
            Console.ReadKey();
        }

        private void ExecuteGenericInstanceMethodInNonGenericClass(object objectToPrint)
        {
            Type typeToPrint = objectToPrint.GetType().GetGenericArguments()[0];

            PrinterB genericPrinter = new PrinterB();
            MethodInfo printSimpleMethod = typeof(PrinterB).GetMethod("PrintSimple");
            MethodInfo printSimpleMethodToExecute = printSimpleMethod.MakeGenericMethod(typeToPrint);

            printSimpleMethodToExecute.Invoke(genericPrinter, new object[] { objectToPrint});
        }

        private void ExecuteGenericStaticMethodInNonGenericClass(object objectToPrint)
        {
            Type typeToPrint = objectToPrint.GetType().GetGenericArguments()[0];
            MethodInfo printPrefixAndSuffixMethod = typeof(PrinterB).GetMethod("PrintPrefixAndSuffix");
            MethodInfo genericprintPrefixAndSuffixMethodToExecute = printPrefixAndSuffixMethod.MakeGenericMethod(typeToPrint);

            genericprintPrefixAndSuffixMethodToExecute.Invoke(null, new object[] { objectToPrint, "My Prefix", "My Suffix" });
        }

        // Executing an overloaded method is more diffcult, the method has to be identified by its parameters
        private void ExecuteGenericOverloadedStaticMethod(object objectToPrint)
        {
            string prefixToPrint = "My Prefix";
            Type overloadType = prefixToPrint.GetType();
            Type typeToPrint = objectToPrint.GetType().GetGenericArguments()[0];
            MethodInfo genricMethodToExecute = GetOverloadedMethod(typeToPrint, overloadType);
            genricMethodToExecute.Invoke(null, new object[] { objectToPrint, prefixToPrint });
        }

        private void ExecuteNonGenericMethodInGenericClass(object objectToPrint)
        {
            Type typeToPrint = objectToPrint.GetType().GetGenericArguments()[0];

            Type printerAType = typeof(PrinterA<>);
            Type genericPrinterAType = printerAType.MakeGenericType(typeToPrint);

            object genericPrinterAInstance = Activator.CreateInstance(genericPrinterAType);
            MethodInfo printMethod = genericPrinterAType.GetMethod("Print");
            printMethod.Invoke(genericPrinterAInstance, new object[] { objectToPrint });
        }

        private MethodInfo GetOverloadedMethod(Type typeToPassToGenericMethod, Type overloadType)
        {
            IEnumerable<MethodInfo> printMethods = typeof(PrinterB).GetMethods().Where(m => m.Name == "PrintPrefix");
            MethodInfo printMethod = printMethods.Single(m => m.GetParameters().Any(p => p.ParameterType == overloadType));
            MethodInfo genericPrintMethod = printMethod.MakeGenericMethod(typeToPassToGenericMethod);
            return genericPrintMethod;
        }
    }
}

Full source code here.

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.