diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs index 27856fe7e4..684e99022b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs @@ -8,6 +8,7 @@ using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies; using Volo.Abp.Caching; using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization; using Volo.Abp.Threading; using Volo.Abp.Users; @@ -107,12 +108,18 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu ApplicationLocalizationDto localizationDto; // In most cases, the culture matches and we can reuse the concurrent request. // If not, we discard it and make a new request with the correct culture. - if (string.Equals(config.Localization.CurrentCulture.Name, cultureName, StringComparison.OrdinalIgnoreCase)) + if (CultureHelper.IsCompatibleCulture(config.Localization.CurrentCulture.Name, cultureName)) { localizationDto = await localizationTask; } else { + // Observe the discarded task to prevent UnobservedTaskException. + _ = localizationTask.ContinueWith( + static t => _ = t.Exception, + TaskContinuationOptions.OnlyOnFaulted + ); + localizationDto = await ApplicationLocalizationClientProxy.GetAsync( new ApplicationLocalizationRequestDto { diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Client.Tests/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Client.Tests/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient_Tests.cs index ed20593873..99c3e552d2 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Client.Tests/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Client.Tests/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient_Tests.cs @@ -6,6 +6,7 @@ using NSubstitute; using Shouldly; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies; +using Volo.Abp.Localization; using Xunit; namespace Volo.Abp.AspNetCore.Mvc.Client; @@ -36,21 +37,24 @@ public class MvcCachedApplicationConfigurationClient_Tests : AbpAspNetCoreMvcCli { var cultureName = "en"; - _configProxy.GetAsync(Arg.Any()).Returns(CreateConfigDto(cultureName)); - - var expectedResources = new Dictionary + using (CultureHelper.Use(cultureName)) { - ["TestResource"] = new() - }; + _configProxy.GetAsync(Arg.Any()).Returns(CreateConfigDto(cultureName)); + + var expectedResources = new Dictionary + { + ["TestResource"] = new() + }; - _localizationProxy.GetAsync(Arg.Any()).Returns(new ApplicationLocalizationDto { Resources = expectedResources }); + _localizationProxy.GetAsync(Arg.Any()).Returns(new ApplicationLocalizationDto { Resources = expectedResources }); - var result = await _applicationConfigurationClient.GetAsync(); + var result = await _applicationConfigurationClient.GetAsync(); - result.Localization.Resources.ShouldBe(expectedResources); + result.Localization.Resources.ShouldBe(expectedResources); - await _configProxy.Received(1).GetAsync(Arg.Is(x => x.IncludeLocalizationResources == false)); - await _localizationProxy.Received(1).GetAsync(Arg.Is(x => x.CultureName == cultureName && x.OnlyDynamics == true)); + await _configProxy.Received(1).GetAsync(Arg.Is(x => x.IncludeLocalizationResources == false)); + await _localizationProxy.Received(1).GetAsync(Arg.Is(x => x.CultureName == cultureName && x.OnlyDynamics == true)); + } } [Fact] @@ -59,22 +63,26 @@ public class MvcCachedApplicationConfigurationClient_Tests : AbpAspNetCoreMvcCli var currentCulture = "en"; var serverCulture = "tr"; - _configProxy.GetAsync(Arg.Any()).Returns(CreateConfigDto(serverCulture)); - - var wrongResources = new Dictionary(); - var correctResources = new Dictionary + using (CultureHelper.Use(currentCulture)) { - ["TestResource"] = new() - }; + _configProxy.GetAsync(Arg.Any()).Returns(CreateConfigDto(serverCulture)); + + var wrongResources = new Dictionary(); + var correctResources = new Dictionary + { + ["TestResource"] = new() + }; - _localizationProxy.GetAsync(Arg.Is(x => x.CultureName == currentCulture)).Returns(new ApplicationLocalizationDto { Resources = wrongResources }); - _localizationProxy.GetAsync(Arg.Is(x => x.CultureName == serverCulture)).Returns(new ApplicationLocalizationDto { Resources = correctResources }); + _localizationProxy.GetAsync(Arg.Is(x => x.CultureName == currentCulture)).Returns(new ApplicationLocalizationDto { Resources = wrongResources }); + _localizationProxy.GetAsync(Arg.Is(x => x.CultureName == serverCulture)).Returns(new ApplicationLocalizationDto { Resources = correctResources }); - var result = await _applicationConfigurationClient.GetAsync(); + var result = await _applicationConfigurationClient.GetAsync(); - result.Localization.Resources.ShouldBe(correctResources); + result.Localization.Resources.ShouldBe(correctResources); - await _localizationProxy.Received(1).GetAsync(Arg.Is(x => x.CultureName == serverCulture)); + await _localizationProxy.Received(1).GetAsync(Arg.Is(x => x.CultureName == currentCulture)); + await _localizationProxy.Received(1).GetAsync(Arg.Is(x => x.CultureName == serverCulture)); + } } private static ApplicationConfigurationDto CreateConfigDto(string cultureName)