I have a .NET 6 web API that does some requests to another third party API, this API has a token that expires after a few hours, so I want to cache this token and reuse in the requests.
Here how I implemented it:
public class TokenInformation
{
public string Token { get; set; }
public DateTime ExpiresIn { get; set; }
}
public static class TokenManagement
{
private static object _lock = new object();
private static TokenInformation _token;
// HttpClient already have credentials and other default headers
public static async Task<string> GetToken(HttpClient httpClient)
{
if (_token is null || _token.ExpiresIn <= DateTime.Now)
{
var response = await httpClient.GetAsync("/token");
if (!response.IsSuccessStatusCode)
throw new Exception($"Authentication Failure: {response.StatusCode}");
var token = await response.Content.ReadAsAsync<TokenInformation>();
lock (_lock)
{
_token = token;
}
}
return _token.Token;
}
}
public class EmployeeServiceClient
{
private HttpClient _httpClient;
public EmployeeServiceClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<string> GetEmployeeDetails(int employeeId)
{
using var message = new HttpRequestMessage(HttpMethod.Get, $"/employee/{employeeId}/details");
message.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", await TokenManagement.GetToken(_httpClient));
var result = await _httpClient.SendAsync(message);
return await result.Content.ReadAsStringAsync();
}
}
My biggest doubt is if I really need the lock
since this is an API with multiple threads and requests. I think so, what you guys think, any tips? Also, should yje lock be wider? If so, since contains async calls should I use .Result
?
Obs. Each class is in a separate file, some class names were changed to hide vendor name, everything else is real code.
lock
. And further, you need thelock
to be broader - around theif
since it accesses_token
as well. \$\endgroup\$.Result
? \$\endgroup\$.Result
is almost always a bad idea. \$\endgroup\$