diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs index 7f4dce5da0..376a3c8446 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs @@ -1,29 +1,35 @@ using System; -using System.Text.RegularExpressions; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.Localization { public class AbpAspNetCoreMvcQueryStringCultureReplacement : IQueryStringCultureReplacement, ITransientDependency { - public virtual Task ReplaceAsync(QueryStringCultureReplacementContext context) + protected AbpQueryStringCultureReplacementOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } + + public AbpAspNetCoreMvcQueryStringCultureReplacement( + IOptions queryStringCultureReplacementOptions, + IServiceProvider serviceProvider) { - var returnUrl = context.ReturnUrl; + ServiceProvider = serviceProvider; + Options = queryStringCultureReplacementOptions.Value; + } - if (!string.IsNullOrWhiteSpace(returnUrl)) + public virtual async Task ReplaceAsync(QueryStringCultureReplacementContext context) + { + using (var scope = ServiceProvider.CreateScope()) { - if (returnUrl.Contains("culture=", StringComparison.OrdinalIgnoreCase)) + foreach (var provider in Options.QueryStringCultureReplacementProviders) { - returnUrl = Regex.Replace(returnUrl, "culture=[A-Za-z-]+?&", $"culture={context.RequestCulture.Culture}&", RegexOptions.Compiled | RegexOptions.IgnoreCase); - } - if (returnUrl.Contains("ui-Culture=", StringComparison.OrdinalIgnoreCase)) - { - returnUrl = Regex.Replace(returnUrl, "ui-culture=[A-Za-z-]+?$", $"ui-culture={context.RequestCulture.UICulture}",RegexOptions.Compiled | RegexOptions.IgnoreCase); + // ReSharper disable once PossibleNullReferenceException + await (scope.ServiceProvider.GetRequiredService(provider) as IQueryStringCultureReplacementProvider) + .ReplaceAsync(context); } } - - return Task.FromResult(returnUrl); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs index d4d4dabe71..b0fa63e4f5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs @@ -33,16 +33,12 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization new RequestCulture(culture, uiCulture) ); - returnUrl = await QueryStringCultureReplacement.ReplaceAsync(new QueryStringCultureReplacementContext() - { - HttpContext = HttpContext, - RequestCulture = new RequestCulture(culture, uiCulture), - ReturnUrl = returnUrl - }); + var context = new QueryStringCultureReplacementContext(HttpContext, new RequestCulture(culture, uiCulture), returnUrl); + await QueryStringCultureReplacement.ReplaceAsync(context); - if (!string.IsNullOrWhiteSpace(returnUrl)) + if (!string.IsNullOrWhiteSpace(context.ReturnUrl)) { - return Redirect(GetRedirectUrl(returnUrl)); + return Redirect(GetRedirectUrl(context.ReturnUrl)); } return Redirect("~/"); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/DefaultQueryStringCultureReplacementProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/DefaultQueryStringCultureReplacementProvider.cs new file mode 100644 index 0000000000..04c7ed4554 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/DefaultQueryStringCultureReplacementProvider.cs @@ -0,0 +1,33 @@ +using System; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + public class DefaultQueryStringCultureReplacementProvider : IQueryStringCultureReplacementProvider, ITransientDependency + { + public Task ReplaceAsync(QueryStringCultureReplacementContext context) + { + if (!string.IsNullOrWhiteSpace(context.ReturnUrl)) + { + if (context.ReturnUrl.Contains("culture=", StringComparison.OrdinalIgnoreCase) && + context.ReturnUrl.Contains("ui-Culture=", StringComparison.OrdinalIgnoreCase)) + { + context.ReturnUrl = Regex.Replace( + context.ReturnUrl, + "culture=[A-Za-z-]+?&", + $"culture={context.RequestCulture.Culture}&", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + context.ReturnUrl = Regex.Replace( + context.ReturnUrl, "ui-culture=[A-Za-z-]+?$", + $"ui-culture={context.RequestCulture.UICulture}", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + } + } + + return Task.CompletedTask; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs index 2635852a6c..7cd8113060 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs @@ -4,6 +4,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization { public interface IQueryStringCultureReplacement { - Task ReplaceAsync(QueryStringCultureReplacementContext context); + Task ReplaceAsync(QueryStringCultureReplacementContext context); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacementProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacementProvider.cs new file mode 100644 index 0000000000..4f4ca7df68 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacementProvider.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + public interface IQueryStringCultureReplacementProvider + { + Task ReplaceAsync(QueryStringCultureReplacementContext context); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs index b537cf2baf..11437a91ce 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs @@ -5,10 +5,17 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization { public class QueryStringCultureReplacementContext { - public HttpContext HttpContext { get; set; } + public HttpContext HttpContext { get; } + + public RequestCulture RequestCulture { get; } public string ReturnUrl { get; set; } - public RequestCulture RequestCulture { get; set; } + public QueryStringCultureReplacementContext(HttpContext httpContext, RequestCulture requestCulture, string returnUrl) + { + HttpContext = httpContext; + RequestCulture = requestCulture; + ReturnUrl = returnUrl; + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementOptions.cs new file mode 100644 index 0000000000..2b3d105ee7 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementOptions.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Collections; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + public class AbpQueryStringCultureReplacementOptions + { + public ITypeList QueryStringCultureReplacementProviders { get; } + + public AbpQueryStringCultureReplacementOptions() + { + QueryStringCultureReplacementProviders = new TypeList(); + QueryStringCultureReplacementProviders.Add(); + } + } +}