Recently I was working on a requirement in ASP.NET Core which needed to invoke a third-party API for fetching some JSON data.The implementation was pretty simple - I had to invoke an external API for every input request and return the records returned by the API; pretty much the role of an aggregator for some underlying data services.But this implementation had a catch - the underlying API which needed to be invoked had a Token Authentication in place. Hence for every request made to the underlying API I had to pass a valid non-expired Access_Token to the API, in order to fetch the data. Furthermore, this token expires after a certain period which needed to be fetched from a Token endpoint.
In such scenarios, where persisting less frequently changed data such as tokens (which may be unchanged for few minutes for example) we can cache the token somewhere and ensure that its reused whenever required until its expiry. This way, I don't need to ask for a Token from the Token Endpoint every time and one less API call means a little better performance.
Where do I cache this token? I can use the InMemory Caching feature that comes with ASP.NET Core.
What is memory caching?
Memory caching (often simply referred to as caching) is a technique in which computer applications temporarily store data in a computer’s main memory (i.e., random access memory, or RAM) to enable fast retrievals of that data. The RAM that is used for the temporary storage is known as the cache. Since accessing RAM is significantly faster than accessing other media like hard disk drives or networks, caching helps applications run faster due to faster access to data. Caching is especially efficient when the application exhibits a common pattern in which it repeatedly accesses data that was previously accessed. Caching is also useful to store data calculations that are otherwise time-consuming to compute. By storing the calculations in a cache, the system saves time by avoiding the repetition of the calculation.
How Does Memory Caching Work?
Memory caching works by first setting aside a portion of RAM to be used as the cache. As an application tries to read data, typically from a data storage system like a database, it checks to see if the desired record already exists in the cache. If it does, then the application will read the data from the cache, thus eliminating the slower access to the database. If the desired record is not in the cache, then the application reads the record from the source. When it retrieves that data, it also writes the data to the cache so that when the application needs that same data in the future, it can quickly get it from the cache.
Let's start
Create a Token is a model class as below:
class Token
{
public string Value { get; set; }
public int ExpiresIn { get; set; }
}
namespace MyNamespace
{
public interface ITokenService
{
string FetchToken();
}
}
namespace MyNamespace
{
public class TokenService : ITokenService
{
private readonly IMemoryCache cache;
public TokenService(IMemoryCache cache)
{
this.cache = cache;
}
public string FetchToken()
{
string token = string.Empty;
// if cache doesn't contain
// an entry called TOKEN
// error handling mechanism is mandatory
if (!cache.TryGetValue("TOKEN", out token))
{
var tokenmodel = this.GetTokenFromApi();
// keep the value within cache for
// given amount of time
// if value is not accessed within the expiry time
// delete the entry from the cache
var options = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(
TimeSpan.FromSeconds(tokenmodel.ExpiresIn));
cache.Set("TOKEN", tokenmodel.Value, options);
token = tokenmodel.Value;
}
return token;
}
private Token GetTokenFromApi()
{
// get api implementation happens here
// returns a token model
}
}
}
I then register this TokenService as a singleton service, along with registering memory cache as a service to the pipeline.
services.AddMemoryCache();
services.AddSingleton<ITokenService, TokenService>();
Now, I can call this method wherever I want the Token to be substituted. For example, I can use this inside my API call code where I need to pass a Token Header. I've implemented it as below:
public class HttpService
{
private ITokenService token;
public HttpService(ITokenService token)
{
this.token = token;
}
public async Task<IEnumerable<Reader>> GetReadersFromExternalApi(string requestUrl)
{
using (HttpClient client = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
request.Headers.Add("Authorization", $"Bearer {token.FetchToken()}");
var res = await client.SendAsync(request);
var readers = JsonConvert.DeserializeObject<List<Reader>>(
await res.Content.ReadAsStringAsync());
return readers;
}
}
}
In this way, I used in-memory caching via IMemoryCache to help persist my intermediate access token for calling external APIs within my application, without having to call the token API repeatedly.
Thanks, for reading the blog, I hope it helps you. Please share this link on your social media accounts so that others can read our valuable content. Share your queries with our expert team and get Free Expert Advice for Your Business today.
Hire me on Linkedin
My portfolio