From 8003e1d43936b58463ae28b060b3a67be8e020cb Mon Sep 17 00:00:00 2001 From: Engincan VESKE Date: Wed, 10 Jun 2026 16:19:52 +0300 Subject: [PATCH 1/3] Use fallback blob provider type. Co-authored-by: Cursor --- .../Volo/Abp/BlobStoring/BlobContainerConfiguration.cs | 8 +++++++- .../Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs | 1 + .../Volo/Abp/BlobStoring/AbpBlobStoringTestModule.cs | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfiguration.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfiguration.cs index fe0a0e09f9..4cc59ff3d0 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfiguration.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfiguration.cs @@ -7,10 +7,16 @@ namespace Volo.Abp.BlobStoring; public class BlobContainerConfiguration { + private Type? _providerType; + /// /// The provider to be used to store BLOBs of this container. /// - public Type? ProviderType { get; set; } + public Type? ProviderType + { + get => _providerType ?? _fallbackConfiguration?.ProviderType; + set => _providerType = value; + } /// /// Indicates whether this container is multi-tenant or not. diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs index 0035cfbe36..5659e9c3c6 100644 --- a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs @@ -33,6 +33,7 @@ public class AbpBlobStoringOptions_Tests : AbpBlobStoringTestBase { var config = _configurationProvider.Get(); config.ProviderType.ShouldBe(typeof(FakeBlobProvider1)); + config.IsMultiTenant.ShouldBeFalse(); config.GetConfigurationOrNull("TestConfigDefault").ShouldBe("TestValueDefault"); } } diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringTestModule.cs index a6746a9480..93523a8c88 100644 --- a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringTestModule.cs @@ -36,6 +36,10 @@ public class AbpBlobStoringTestModule : AbpModule { container.SetConfiguration("TestConfig2", "TestValue2"); container.ProviderType = typeof(FakeBlobProvider2); + }) + .Configure(container => + { + container.IsMultiTenant = false; }); }); } From 14187dbbd8d31051b4988daa359c5e8e1e4a8f52 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Jun 2026 13:30:35 +0000 Subject: [PATCH 2/3] Rename test to reflect fallback behavior when ProviderType is not explicitly configured --- .../Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs index 5659e9c3c6..c0ac4301d5 100644 --- a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs @@ -29,7 +29,7 @@ public class AbpBlobStoringOptions_Tests : AbpBlobStoringTestBase } [Fact] - public void Should_Fallback_To_Default_Configuration_If_Not_Specialized() + public void Should_Fallback_To_Default_ProviderType_When_Not_Explicitly_Configured() { var config = _configurationProvider.Get(); config.ProviderType.ShouldBe(typeof(FakeBlobProvider1)); From a249f2a5a8339193ad804d90487056c7266176a2 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 11 Jun 2026 13:15:09 +0800 Subject: [PATCH 3/3] Add NamingNormalizers fallback bound to ProviderType inheritance --- .../BlobStoring/BlobContainerConfiguration.cs | 14 +++++ .../BlobStoring/BlobNormalizeNamingService.cs | 16 +---- .../AbpBlobStoringOptions_Tests.cs | 11 ++++ .../BlobContainerConfiguration_Tests.cs | 62 +++++++++++++++++++ .../Fakes/AnotherFakeNamingNormalizer.cs | 14 +++++ .../BlobStoring/Fakes/FakeNamingNormalizer.cs | 14 +++++ 6 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainerConfiguration_Tests.cs create mode 100644 framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/Fakes/AnotherFakeNamingNormalizer.cs create mode 100644 framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/Fakes/FakeNamingNormalizer.cs diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfiguration.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfiguration.cs index 4cc59ff3d0..3d6cd86941 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfiguration.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerConfiguration.cs @@ -43,6 +43,20 @@ public class BlobContainerConfiguration _properties = new Dictionary(); } + /// + /// Returns the naming normalizers in effect for this container, inheriting from the fallback + /// configuration only when this container has none and does not override . + /// + public IEnumerable GetEffectiveNamingNormalizers() + { + if (NamingNormalizers.Count == 0 && _providerType == null && _fallbackConfiguration != null) + { + return _fallbackConfiguration.GetEffectiveNamingNormalizers(); + } + + return NamingNormalizers; + } + public T? GetConfigurationOrDefault(string name, T? defaultValue = default) { return (T?)GetConfigurationOrNull(name, defaultValue); diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNamingService.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNamingService.cs index 397b48ca0c..cd1ae931b5 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNamingService.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobNormalizeNamingService.cs @@ -19,15 +19,15 @@ public class BlobNormalizeNamingService : IBlobNormalizeNamingService, ITransien string? containerName, string? blobName) { - - if (!configuration.NamingNormalizers.Any()) + var normalizerTypes = configuration.GetEffectiveNamingNormalizers(); + if (!normalizerTypes.Any()) { return new BlobNormalizeNaming(containerName, blobName); } using (var scope = ServiceProvider.CreateScope()) { - foreach (var normalizerType in configuration.NamingNormalizers) + foreach (var normalizerType in normalizerTypes) { var normalizer = scope.ServiceProvider .GetRequiredService(normalizerType) @@ -43,21 +43,11 @@ public class BlobNormalizeNamingService : IBlobNormalizeNamingService, ITransien public string NormalizeContainerName(BlobContainerConfiguration configuration, string containerName) { - if (!configuration.NamingNormalizers.Any()) - { - return containerName; - } - return NormalizeNaming(configuration, containerName, null).ContainerName!; } public string NormalizeBlobName(BlobContainerConfiguration configuration, string blobName) { - if (!configuration.NamingNormalizers.Any()) - { - return blobName; - } - return NormalizeNaming(configuration, null, blobName).BlobName!; } } diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs index c0ac4301d5..48c4c6948f 100644 --- a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/AbpBlobStoringOptions_Tests.cs @@ -36,4 +36,15 @@ public class AbpBlobStoringOptions_Tests : AbpBlobStoringTestBase config.IsMultiTenant.ShouldBeFalse(); config.GetConfigurationOrNull("TestConfigDefault").ShouldBe("TestValueDefault"); } + + [Fact] + public void Should_Resolve_Fallback_Chain_Through_Configuration_Provider() + { + var testContainer1Config = _configurationProvider.Get(); + testContainer1Config.IsMultiTenant.ShouldBeTrue(); + + var testContainer3Config = _configurationProvider.Get(); + testContainer3Config.IsMultiTenant.ShouldBeFalse(); + testContainer3Config.ProviderType.ShouldBe(typeof(FakeBlobProvider1)); + } } diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainerConfiguration_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainerConfiguration_Tests.cs new file mode 100644 index 0000000000..f47faa1f25 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainerConfiguration_Tests.cs @@ -0,0 +1,62 @@ +using System.Linq; +using Shouldly; +using Volo.Abp.BlobStoring.Fakes; +using Xunit; + +namespace Volo.Abp.BlobStoring; + +public class BlobContainerConfiguration_Tests +{ + [Fact] + public void Should_Override_Default_Container_ProviderType_When_Named_Container_Has_Its_Own() + { + var defaultConfig = new BlobContainerConfiguration(); + defaultConfig.ProviderType = typeof(FakeBlobProvider1); + + var namedConfig = new BlobContainerConfiguration(defaultConfig); + namedConfig.ProviderType = typeof(FakeBlobProvider2); + + namedConfig.ProviderType.ShouldBe(typeof(FakeBlobProvider2)); + defaultConfig.ProviderType.ShouldBe(typeof(FakeBlobProvider1)); + } + + [Fact] + public void Should_Inherit_Default_Container_NamingNormalizers_When_Provider_Also_Inherited() + { + var defaultConfig = new BlobContainerConfiguration(); + defaultConfig.ProviderType = typeof(FakeBlobProvider1); + defaultConfig.NamingNormalizers.Add(); + + var namedConfig = new BlobContainerConfiguration(defaultConfig); + + namedConfig.GetEffectiveNamingNormalizers().ShouldContain(typeof(FakeNamingNormalizer)); + namedConfig.NamingNormalizers.ShouldBeEmpty(); + } + + [Fact] + public void Should_Not_Inherit_NamingNormalizers_When_Named_Container_Has_Its_Own_ProviderType() + { + var defaultConfig = new BlobContainerConfiguration(); + defaultConfig.ProviderType = typeof(FakeBlobProvider1); + defaultConfig.NamingNormalizers.Add(); + + var namedConfig = new BlobContainerConfiguration(defaultConfig); + namedConfig.ProviderType = typeof(FakeBlobProvider2); + + namedConfig.GetEffectiveNamingNormalizers().ShouldBeEmpty(); + } + + [Fact] + public void Should_Override_Default_Container_NamingNormalizers_When_Named_Container_Has_Its_Own() + { + var defaultConfig = new BlobContainerConfiguration(); + defaultConfig.NamingNormalizers.Add(); + + var namedConfig = new BlobContainerConfiguration(defaultConfig); + namedConfig.NamingNormalizers.Add(); + + var effective = namedConfig.GetEffectiveNamingNormalizers().ToList(); + effective.ShouldContain(typeof(AnotherFakeNamingNormalizer)); + effective.ShouldNotContain(typeof(FakeNamingNormalizer)); + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/Fakes/AnotherFakeNamingNormalizer.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/Fakes/AnotherFakeNamingNormalizer.cs new file mode 100644 index 0000000000..60e53b5c2a --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/Fakes/AnotherFakeNamingNormalizer.cs @@ -0,0 +1,14 @@ +namespace Volo.Abp.BlobStoring.Fakes; + +public class AnotherFakeNamingNormalizer : IBlobNamingNormalizer +{ + public string NormalizeContainerName(string containerName) + { + return containerName; + } + + public string NormalizeBlobName(string blobName) + { + return blobName; + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/Fakes/FakeNamingNormalizer.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/Fakes/FakeNamingNormalizer.cs new file mode 100644 index 0000000000..a5a32a0d6d --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/Fakes/FakeNamingNormalizer.cs @@ -0,0 +1,14 @@ +namespace Volo.Abp.BlobStoring.Fakes; + +public class FakeNamingNormalizer : IBlobNamingNormalizer +{ + public string NormalizeContainerName(string containerName) + { + return containerName; + } + + public string NormalizeBlobName(string blobName) + { + return blobName; + } +}