From 5f933a6afbb3d7adf3e45e922069fdd05482829a Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 2 Mar 2026 14:39:03 +0800 Subject: [PATCH 1/4] Fix cache key isolation by user identity in MvcCachedApplicationConfigurationClient --- .../MvcCachedApplicationConfigurationClient.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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 e3d3c12370..396aa728b8 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 @@ -14,7 +14,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client; public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency { - private const string ApplicationConfigurationDtoCacheKey = "ApplicationConfigurationDto_CacheKey"; + private const string ApplicationConfigurationDtoCacheKeyFormat = "ApplicationConfigurationDto_{0}_CacheKey"; protected IHttpContextAccessor HttpContextAccessor { get; } protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; } @@ -46,7 +46,8 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu { string? cacheKey = null; var httpContext = HttpContextAccessor?.HttpContext; - if (httpContext != null && httpContext.Items[ApplicationConfigurationDtoCacheKey] is string key) + var itemsKey = string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous"); + if (httpContext != null && httpContext.Items[itemsKey] is string key) { cacheKey = key; } @@ -56,7 +57,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu cacheKey = await CreateCacheKeyAsync(); if (httpContext != null) { - httpContext.Items[ApplicationConfigurationDtoCacheKey] = cacheKey; + httpContext.Items[itemsKey] = cacheKey; } } @@ -107,7 +108,8 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu { string? cacheKey = null; var httpContext = HttpContextAccessor?.HttpContext; - if (httpContext != null && httpContext.Items[ApplicationConfigurationDtoCacheKey] is string key) + var itemsKey = string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous"); + if (httpContext != null && httpContext.Items[itemsKey] is string key) { cacheKey = key; } @@ -117,7 +119,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu cacheKey = AsyncHelper.RunSync(CreateCacheKeyAsync); if (httpContext != null) { - httpContext.Items[ApplicationConfigurationDtoCacheKey] = cacheKey; + httpContext.Items[itemsKey] = cacheKey; } } @@ -133,4 +135,5 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu { return await CacheHelper.CreateCacheKeyAsync(CurrentUser.Id); } + } From ddf9b04b4407017a949ac29e307185063b8d9be1 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 2 Mar 2026 14:46:45 +0800 Subject: [PATCH 2/4] Include UI culture in the HttpContext.Items cache key --- .../Mvc/Client/MvcCachedApplicationConfigurationClient.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 396aa728b8..a87a84cf21 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 @@ -1,4 +1,5 @@ using System; +using System.Globalization; using Microsoft.AspNetCore.Http; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Distributed; @@ -14,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client; public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency { - private const string ApplicationConfigurationDtoCacheKeyFormat = "ApplicationConfigurationDto_{0}_CacheKey"; + private const string ApplicationConfigurationDtoCacheKeyFormat = "ApplicationConfigurationDto_{0}_{1}_CacheKey"; protected IHttpContextAccessor HttpContextAccessor { get; } protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; } @@ -46,7 +47,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu { string? cacheKey = null; var httpContext = HttpContextAccessor?.HttpContext; - var itemsKey = string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous"); + var itemsKey = string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous", CultureInfo.CurrentUICulture.Name); if (httpContext != null && httpContext.Items[itemsKey] is string key) { cacheKey = key; @@ -108,7 +109,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu { string? cacheKey = null; var httpContext = HttpContextAccessor?.HttpContext; - var itemsKey = string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous"); + var itemsKey = string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous", CultureInfo.CurrentUICulture.Name); if (httpContext != null && httpContext.Items[itemsKey] is string key) { cacheKey = key; From b59fc27c1d4ca7c8407046578d310d483d060c2a Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 2 Mar 2026 14:51:25 +0800 Subject: [PATCH 3/4] Extract GetHttpContextItemsCacheKey helper method --- .../Mvc/Client/MvcCachedApplicationConfigurationClient.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 a87a84cf21..c1cc7d52fe 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 @@ -47,7 +47,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu { string? cacheKey = null; var httpContext = HttpContextAccessor?.HttpContext; - var itemsKey = string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous", CultureInfo.CurrentUICulture.Name); + var itemsKey = GetHttpContextItemsCacheKey(); if (httpContext != null && httpContext.Items[itemsKey] is string key) { cacheKey = key; @@ -109,7 +109,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu { string? cacheKey = null; var httpContext = HttpContextAccessor?.HttpContext; - var itemsKey = string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous", CultureInfo.CurrentUICulture.Name); + var itemsKey = GetHttpContextItemsCacheKey(); if (httpContext != null && httpContext.Items[itemsKey] is string key) { cacheKey = key; @@ -137,4 +137,8 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu return await CacheHelper.CreateCacheKeyAsync(CurrentUser.Id); } + protected virtual string GetHttpContextItemsCacheKey() + { + return string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous", CultureInfo.CurrentUICulture.Name); + } } From 4c20961b155a65b12e90684cb0c9546d390141c3 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 2 Mar 2026 14:58:45 +0800 Subject: [PATCH 4/4] Rename constant and use InvariantCulture for cache key formatting --- .../Mvc/Client/MvcCachedApplicationConfigurationClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 c1cc7d52fe..70761d7fca 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 @@ -15,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client; public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency { - private const string ApplicationConfigurationDtoCacheKeyFormat = "ApplicationConfigurationDto_{0}_{1}_CacheKey"; + private const string HttpContextItemsCacheKeyFormat = "ApplicationConfigurationDto_{0}_{1}_CacheKey"; protected IHttpContextAccessor HttpContextAccessor { get; } protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; } @@ -139,6 +139,6 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu protected virtual string GetHttpContextItemsCacheKey() { - return string.Format(ApplicationConfigurationDtoCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous", CultureInfo.CurrentUICulture.Name); + return string.Format(CultureInfo.InvariantCulture, HttpContextItemsCacheKeyFormat, CurrentUser.Id?.ToString("N") ?? "Anonymous", CultureInfo.CurrentUICulture.Name); } }