I'm trying to enable client caching of the System.Net.HttpClient. I have an endpoint at http://localhost:83/api/test that takes 1 second to respond and it sends cache headers back.
If I have this code
static async Task MainAsync()
{
var client = new HttpClient(new WebRequestHandler { CachePolicy = new HttpRequestCachePolicy() }) { BaseAddress = new Uri("http://localhost:83/api/") };
for (int i = 0; i < 20; i++)
{
var response = await client.GetAsync("test");
var res = await response.Content.ReadAsStringAsync();
Console.WriteLine(res);
}
}
It takes one second to execute.
If I put the same code into an api controller
static HttpClient client = new HttpClient(new WebRequestHandler {CachePolicy = new HttpRequestCachePolicy() }) { BaseAddress = new Uri("http://localhost:83/api/") };
public async Task<string> Get()
{
for (int i = 0; i < 20; i++)
{
var response = await client.GetAsync("test");
var res = await response.Content.ReadAsStringAsync();
}
return "ok";
}
And host it in IIS it takes 20 seconds to respond.
What do I need to do in order to enable client cache from server applications?
Probably you should switch to WinHTTP and use another HTTP caching implementation.
There are two HTTP client APIs that .NET Framework uses. One provided by WinINet and another by WinHTTP. .NET Framework uses WinINet by default. But WinINet was developed to work in client applications and it is not suppose to work in server environment. Relevant quote from Windows Internet page on MSDN:
Where applicable
WinINet does not support server implementations. In addition, it should not be used from a service. For server implementations or services use Microsoft Windows HTTP Services (WinHTTP).
So in your Web API you need to use WinHTTP. The only way to switch that I know is to use WinHttpHandler from System.Net.Http.WinHttpHandler NuGet package. But currently this handler do not use HTTP caching. It has no way to set cache policy and it ignores all settings that HttpClientHandler respect. See How do I utilize HTTP caching with WinHttpHandler and HttpClient? issue on GitHub.
To fix this you can implement your own caching mechanism or use existing one like CacheCow project. It has built-in in-memory storage and it's own implementation of DelagatingHandler for HttpClient.
Note that currently there are some compatibility issues and you need to manually remove reference to .NET Framework System.Net.Http from your Web API project before installing System.Net.Http.WinHttpHandler and CacheCow.Clien NuGet packages. Following code snipped demonstrates usage of WinHttpHandler and CachingHandler from CacheCow.Clien NuGet package:
static HttpClient client = new HttpClient(new CachingHandler { InnerHandler = new WinHttpHandler() })
{
BaseAddress = new Uri("http://localhost:83/api/")
};
For more information check:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With