From b145b505acfe687b3d6aa7e86f3aa42876da161b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Gether=20S=C3=B8rensen?= Date: Thu, 5 Jun 2025 19:53:48 +0200 Subject: [PATCH] Add Microsoft.Extensions.Caching.Memory and Microsoft.Extensions.DependencyInjection packages for improved caching and dependency management --- .../DataverseConnection.csproj | 2 ++ .../ServiceCollectionExtensions.cs | 29 ++++++++++++++++++- DataverseWhoAmI/DataverseWhoAmI.csproj | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/DataverseConnection/DataverseConnection.csproj b/DataverseConnection/DataverseConnection.csproj index 90410b6..1cc72da 100644 --- a/DataverseConnection/DataverseConnection.csproj +++ b/DataverseConnection/DataverseConnection.csproj @@ -14,6 +14,8 @@ + + diff --git a/DataverseConnection/ServiceCollectionExtensions.cs b/DataverseConnection/ServiceCollectionExtensions.cs index 68226d2..27c6666 100644 --- a/DataverseConnection/ServiceCollectionExtensions.cs +++ b/DataverseConnection/ServiceCollectionExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.PowerPlatform.Dataverse.Client; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Caching.Memory; namespace DataverseConnection { @@ -40,6 +41,9 @@ public static IServiceCollection AddDataverse(this IServiceCollection services, var options = new DataverseOptions(); configureOptions?.Invoke(options); + // Ensure MemoryCache is registered + services.AddMemoryCache(); + services.AddSingleton(sp => { // Determine DataverseUrl: options first, then configuration @@ -56,11 +60,34 @@ public static IServiceCollection AddDataverse(this IServiceCollection services, var credential = options.TokenCredential ?? new DefaultAzureCredential(); var resource = $"{new Uri(dataverseUrl).GetLeftPart(UriPartial.Authority)}/.default"; + var memoryCache = sp.GetRequiredService(); + // Token provider function for ServiceClient async Task TokenProvider(string url) { - var tokenRequestContext = new TokenRequestContext(new[] { resource }); + var cacheKey = $"dataverse_token_{resource}"; + if (memoryCache.TryGetValue(cacheKey, out var cachedToken) && cachedToken != null) + return cachedToken; + + var tokenRequestContext = new TokenRequestContext([resource]); var token = await credential.GetTokenAsync(tokenRequestContext, default); + + // Set expiration 5 minutes before actual expiry, but never in the past + var expiresOn = token.ExpiresOn.UtcDateTime; + var now = DateTime.UtcNow; + var expiration = expiresOn - TimeSpan.FromMinutes(5); + if (expiration <= now) + { + // If token lifetime is less than 5 minutes, expire 1 minute before, or immediately if needed + expiration = expiresOn > now.AddMinutes(1) ? expiresOn - TimeSpan.FromMinutes(1) : now.AddSeconds(10); + } + + var cacheEntryOptions = new MemoryCacheEntryOptions + { + AbsoluteExpiration = expiration + }; + memoryCache.Set(cacheKey, token.Token, cacheEntryOptions); + return token.Token; } diff --git a/DataverseWhoAmI/DataverseWhoAmI.csproj b/DataverseWhoAmI/DataverseWhoAmI.csproj index a4de6c7..2e903d9 100644 --- a/DataverseWhoAmI/DataverseWhoAmI.csproj +++ b/DataverseWhoAmI/DataverseWhoAmI.csproj @@ -22,6 +22,7 @@ +