Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DataverseConnection/DataverseConnection.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.2" />
<PackageReference Include="Microsoft.PowerPlatform.Dataverse.Client" Version="1.2.7" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
</ItemGroup>

</Project>
29 changes: 28 additions & 1 deletion DataverseConnection/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.PowerPlatform.Dataverse.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Caching.Memory;

namespace DataverseConnection
{
Expand Down Expand Up @@ -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
Expand All @@ -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<IMemoryCache>();

// Token provider function for ServiceClient
async Task<string> TokenProvider(string url)
{
var tokenRequestContext = new TokenRequestContext(new[] { resource });
var cacheKey = $"dataverse_token_{resource}";
if (memoryCache.TryGetValue<string>(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;
}

Expand Down
1 change: 1 addition & 0 deletions DataverseWhoAmI/DataverseWhoAmI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
Expand Down
Loading