So, I have an ASP.NET Core 3.1 web site that makes occasional calls to a vendor's RESTful API. I use the HttpClient
class to perform these calls.
Currently, the web site is relatively low traffic (probably a couple of users per day). The current primary use case will result in 3 calls to the API for the complete workflow.
Even in previous versions of the framework, Microsoft recommended just creating a single instance of HttpClient
and using it throughout the entire lifecycle of your application (to prevent port exhaustion). The new recommendation for ASP.NET Core is to register a service in your Startup
class to act as a factory for your HttpClient
. I initially used my own Singleton for but recently switched to follow Microsoft's recommendation.
My one concern is that I have to add my API Key as a header for each request, or it will be rejected.
I currently store the database key in SQL Server, using its always-encrypted feature to make sure that it stays private.
Here's the relevant logic in the ConfigureServices
method in my Startup
class:
services.AddDbContext<DatabaseContext>();
// Use TLS 1.3 for requests
// I'm a little uncertain if this is still the recommended way to configure this in ASP.NET Core
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13;
services.AddHttpClient("VendorAPICall", c =>
{
c.BaseAddress = new Uri("https://api.vendorname.com/");
c.Timeout = new TimeSpan(4, 0, 0);
c.DefaultRequestHeaders.Accept.Clear();
c.DefaultRequestHeaders.Add("Accept", "application/json");
// I store the API Key securely using SQL Server's Always Encrypted feature: https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/always-encrypted-database-engine?view=sql-server-ver15
// I'm a little concerned about the potential performance impact of this, especially how
// many extra database calls it could result in (particularly since I'm not doing
// the async calls).
using (var ctx = new DatabaseContext())
{
Security security = ctx.Security.First();
// Header must include the API Token for all requests, or the request will be rejected
c.DefaultRequestHeaders.Add("ApiToken", security.Apikey);
}
});
I have two points that I'm concerned about:
First, is the call to ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13;
still the recommended (or, at least, acceptable) way of doing this configuration in ASP.NET Core, or am I doing this wrong?
Secondly, I'm concerned about the database call and how many back-and-forths this could result in for the database. This seems a little unnecessary, since the API Key will only be renewed every 6 months or so, so it seems wasteful at a minimum and a potential scalability issue at worst.
I'm also a little annoyed that I'm not using the async
version of the Entity Framework calls here. (I'm otherwise using the async version of all of the database calls wherever possible).
Am I worrying too much here, or is there actually a better way to do this? (I already established in a separate Q&A on Stack Overflow that I was, in fact, being paranoid about the possibility of keeping the API Key in memory, but that's probably a separate issue).