From e1a65f3abd2417bc00609978de33fce7a78cfdfb Mon Sep 17 00:00:00 2001 From: hangy Date: Wed, 16 Jul 2025 20:00:24 +0200 Subject: [PATCH 1/3] feat(DataProtection): add overloads for PersistKeysToStackExchangeRedis to accept IServiceProvider --- .../src/PublicAPI.Unshipped.txt | 2 + .../RedisDataProtectionBuilderExtensions.cs | 40 ++++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt b/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt index 7dc5c58110bf..9673342076e9 100644 --- a/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt +++ b/src/DataProtection/StackExchangeRedis/src/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ #nullable enable +static Microsoft.AspNetCore.DataProtection.StackExchangeRedisDataProtectionBuilderExtensions.PersistKeysToStackExchangeRedis(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Func! databaseFactory) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! +static Microsoft.AspNetCore.DataProtection.StackExchangeRedisDataProtectionBuilderExtensions.PersistKeysToStackExchangeRedis(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! builder, System.Func! databaseFactory, StackExchange.Redis.RedisKey key) -> Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder! diff --git a/src/DataProtection/StackExchangeRedis/src/RedisDataProtectionBuilderExtensions.cs b/src/DataProtection/StackExchangeRedis/src/RedisDataProtectionBuilderExtensions.cs index 82a8a8c69012..104be9449c9b 100644 --- a/src/DataProtection/StackExchangeRedis/src/RedisDataProtectionBuilderExtensions.cs +++ b/src/DataProtection/StackExchangeRedis/src/RedisDataProtectionBuilderExtensions.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.DataProtection.StackExchangeRedis; using Microsoft.AspNetCore.Shared; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using StackExchange.Redis; namespace Microsoft.AspNetCore.DataProtection; @@ -28,7 +29,7 @@ public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataP { ArgumentNullThrowHelper.ThrowIfNull(builder); ArgumentNullThrowHelper.ThrowIfNull(databaseFactory); - return PersistKeysToStackExchangeRedisInternal(builder, databaseFactory, key); + return PersistKeysToStackExchangeRedisInternal(builder, _ => databaseFactory(), key); } /// @@ -53,15 +54,44 @@ public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataP { ArgumentNullThrowHelper.ThrowIfNull(builder); ArgumentNullThrowHelper.ThrowIfNull(connectionMultiplexer); - return PersistKeysToStackExchangeRedisInternal(builder, () => connectionMultiplexer.GetDatabase(), key); + return PersistKeysToStackExchangeRedisInternal(builder, _ => connectionMultiplexer.GetDatabase(), key); + } + + /// + /// Configures the data protection system to persist keys to the default key ('DataProtection-Keys') in Redis database + /// + /// The builder instance to modify. + /// The for database access. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataProtectionBuilder builder, Func databaseFactory) + { + return PersistKeysToStackExchangeRedis(builder, databaseFactory, DataProtectionKeysName); + } + + /// + /// Configures the data protection system to persist keys to the specified key in Redis database + /// + /// The builder instance to modify. + /// The for database access. + /// The used to store key list. + /// A reference to the after this operation has completed. + public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataProtectionBuilder builder, Func databaseFactory, RedisKey key) + { + ArgumentNullThrowHelper.ThrowIfNull(builder); + ArgumentNullThrowHelper.ThrowIfNull(databaseFactory); + return PersistKeysToStackExchangeRedisInternal(builder, databaseFactory, key); } - private static IDataProtectionBuilder PersistKeysToStackExchangeRedisInternal(IDataProtectionBuilder builder, Func databaseFactory, RedisKey key) + private static IDataProtectionBuilder PersistKeysToStackExchangeRedisInternal(IDataProtectionBuilder builder, Func databaseFactory, RedisKey key) { - builder.Services.Configure(options => + builder.Services.AddSingleton>(services => { - options.XmlRepository = new RedisXmlRepository(databaseFactory, key); + return new ConfigureOptions(options => + { + options.XmlRepository = new RedisXmlRepository(() => databaseFactory(services), key); + }); }); + return builder; } } From 29326f3bec3adc5e14d4d1ccbbda85247149ff3c Mon Sep 17 00:00:00 2001 From: hangy Date: Wed, 16 Jul 2025 20:23:37 +0200 Subject: [PATCH 2/3] test(DataProtection): add unit test for PersistKeysToStackExchangeRedis factory method --- .../RedisDataProtectionBuilderExtensionsTest.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/DataProtection/StackExchangeRedis/test/RedisDataProtectionBuilderExtensionsTest.cs b/src/DataProtection/StackExchangeRedis/test/RedisDataProtectionBuilderExtensionsTest.cs index 34ea9081f2e3..9a5cefd05e60 100644 --- a/src/DataProtection/StackExchangeRedis/test/RedisDataProtectionBuilderExtensionsTest.cs +++ b/src/DataProtection/StackExchangeRedis/test/RedisDataProtectionBuilderExtensionsTest.cs @@ -28,4 +28,21 @@ public void PersistKeysToRedis_UsesRedisXmlRepository() var options = services.GetRequiredService>(); Assert.IsType(options.Value.XmlRepository); } + + [Fact] + public void PersistKeysToRedis_FactoryMethod_UsesRedisXmlRepository() + { + // Arrange + var connection = Mock.Of(); + var serviceCollection = new ServiceCollection(); + var builder = serviceCollection.AddDataProtection(); + + // Act + builder.PersistKeysToStackExchangeRedis(services => services.GetRequiredService().GetDatabase()); + var services = serviceCollection.BuildServiceProvider(); + + // Assert + var options = services.GetRequiredService>(); + Assert.IsType(options.Value.XmlRepository); + } } From 688863f8c1d919c1f3df6b9938bb4773fd7c4fe9 Mon Sep 17 00:00:00 2001 From: hangy Date: Wed, 16 Jul 2025 20:36:53 +0200 Subject: [PATCH 3/3] docs(DataProtection): update databaseFactory parameter documentation to clarify usage with IServiceProvider --- .../src/RedisDataProtectionBuilderExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DataProtection/StackExchangeRedis/src/RedisDataProtectionBuilderExtensions.cs b/src/DataProtection/StackExchangeRedis/src/RedisDataProtectionBuilderExtensions.cs index 104be9449c9b..6ac3b2c5f156 100644 --- a/src/DataProtection/StackExchangeRedis/src/RedisDataProtectionBuilderExtensions.cs +++ b/src/DataProtection/StackExchangeRedis/src/RedisDataProtectionBuilderExtensions.cs @@ -61,7 +61,7 @@ public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataP /// Configures the data protection system to persist keys to the default key ('DataProtection-Keys') in Redis database /// /// The builder instance to modify. - /// The for database access. + /// A factory function that uses to create an instance. /// A reference to the after this operation has completed. public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataProtectionBuilder builder, Func databaseFactory) { @@ -72,7 +72,7 @@ public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataP /// Configures the data protection system to persist keys to the specified key in Redis database /// /// The builder instance to modify. - /// The for database access. + /// A factory function that uses to create an instance. /// The used to store key list. /// A reference to the after this operation has completed. public static IDataProtectionBuilder PersistKeysToStackExchangeRedis(this IDataProtectionBuilder builder, Func databaseFactory, RedisKey key)