You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET运行时更新RequestLocalizationOptions无需重启应用

解决方案:.NET运行时动态更新RequestLocalizationOptions

要实现运行时新增文化后无需重启应用更新本地化配置,核心是解决启动时一次性加载的问题,通过缓存+动态选项更新的方式实现。以下是具体步骤:


1. 修复启动时异步配置的潜在问题

原代码中services.Configure<RequestLocalizationOptions>使用异步委托是无效的(Configure仅接受同步Action),会导致启动时数据库查询未完成就继续初始化,可能出现初始文化列表为空的情况。我们改为用文化管理服务统一处理文化加载逻辑。

2. 实现带缓存的文化管理服务

创建ICultureManager及其实现类,结合内存缓存避免频繁查询数据库,同时支持手动刷新缓存:

public interface ICultureManager
{
    Task<IList<CultureInfo>> GetSupportedCulturesAsync();
    void RefreshCultures();
}

public class CultureManager : ICultureManager
{
    private readonly ICultureService _cultureService;
    private readonly IMemoryCache _cache;
    private const string _cacheKey = "SupportedCultures";
    private readonly TimeSpan _cacheExpiration = TimeSpan.FromMinutes(5); // 可根据需求调整缓存时长

    public CultureManager(ICultureService cultureService, IMemoryCache cache)
    {
        _cultureService = cultureService;
        _cache = cache;
    }

    public async Task<IList<CultureInfo>> GetSupportedCulturesAsync()
    {
        return await _cache.GetOrCreateAsync(_cacheKey, async entry =>
        {
            entry.AbsoluteExpirationRelativeToNow = _cacheExpiration;
            var dbCultures = await _cultureService.GetFromDatabase(x => x.Available == true);
            return dbCultures.Select(c => new CultureInfo($"{c.language}-{c.CountryCodeIso2}")).ToList();
        });
    }

    public void RefreshCultures()
    {
        _cache.Remove(_cacheKey);
    }
}

3. 重构本地化选项配置

修改AddRequestLocalizationOptions扩展方法,注册文化管理服务,并初始化基础配置:

public static IServiceCollection AddRequestLocalizationOptions(this IServiceCollection services)
{
    // 注册文化管理服务
    services.AddScoped<ICultureManager, CultureManager>();
    // 注册内存缓存
    services.AddMemoryCache();

    // 初始化RequestLocalizationOptions基础配置
    services.Configure<RequestLocalizationOptions>(options =>
    {
        options.DefaultRequestCulture = new RequestCulture("en-US");
        options.RequestCultureProviders = new List<IRequestCultureProvider>
        {
            new CookieRequestCultureProvider
            {
                CookieName = CookieDefaults.CultureKey
            }
        };
    });

    return services;
}

4. 启动时加载初始文化列表

在Program.cs中,应用启动后立即加载初始文化并更新选项:

var app = builder.Build();

// 初始化初始文化列表
using var scope = app.Services.CreateScope();
var cultureManager = scope.ServiceProvider.GetRequiredService<ICultureManager>();
var initialCultures = await cultureManager.GetSupportedCulturesAsync();
var optionsMonitor = scope.ServiceProvider.GetRequiredService<IOptionsMonitor<RequestLocalizationOptions>>();
var currentOptions = optionsMonitor.CurrentValue;

currentOptions.SupportedCultures = initialCultures;
currentOptions.SupportedUICultures = initialCultures;

// 启用本地化中间件
app.UseRequestLocalization();

// 其他中间件配置...
app.Run();

5. 实现运行时刷新接口

添加API接口,用于手动触发文化更新(比如新增文化后调用此接口):

[ApiController]
[Route("api/culture")]
public class CultureController : ControllerBase
{
    private readonly ICultureManager _cultureManager;
    private readonly IOptionsMonitor<RequestLocalizationOptions> _optionsMonitor;

    public CultureController(ICultureManager cultureManager, IOptionsMonitor<RequestLocalizationOptions> optionsMonitor)
    {
        _cultureManager = cultureManager;
        _optionsMonitor = optionsMonitor;
    }

    [HttpPost("refresh")]
    public async Task<IActionResult> RefreshCultures()
    {
        // 清除缓存,重新从数据库加载
        _cultureManager.RefreshCultures();
        var latestCultures = await _cultureManager.GetSupportedCulturesAsync();

        // 更新RequestLocalizationOptions
        var currentOptions = _optionsMonitor.CurrentValue;
        currentOptions.SupportedCultures = latestCultures;
        currentOptions.SupportedUICultures = latestCultures;

        return Ok("支持文化列表已更新");
    }
}

6. 可选:添加文化验证逻辑(避免无效文化)

如果需要确保请求的文化始终在支持列表中,可以自定义RequestCultureProvider,在每次请求时验证:

public class ValidatingCultureProvider : IRequestCultureProvider
{
    private readonly ICultureManager _cultureManager;

    public ValidatingCultureProvider(ICultureManager cultureManager)
    {
        _cultureManager = cultureManager;
    }

    public async Task<ProviderCultureResult?> DetermineProviderCultureResult(HttpContext httpContext)
    {
        var cookieCulture = httpContext.Request.Cookies[CookieDefaults.CultureKey];
        if (string.IsNullOrEmpty(cookieCulture)) return null;

        var supportedCultures = await _cultureManager.GetSupportedCulturesAsync();
        if (!supportedCultures.Any(c => c.Name.Equals(cookieCulture, StringComparison.OrdinalIgnoreCase)))
        {
            // 若请求的文化不在支持列表中,返回默认文化
            return new ProviderCultureResult("en-US");
        }

        return null; // 交由后续提供器处理
    }
}

然后在配置RequestLocalizationOptions时添加此提供器:

services.Configure<RequestLocalizationOptions>(options =>
{
    options.DefaultRequestCulture = new RequestCulture("en-US");
    options.RequestCultureProviders = new List<IRequestCultureProvider>
    {
        new CookieRequestCultureProvider
        {
            CookieName = CookieDefaults.CultureKey
        },
        new ValidatingCultureProvider(scope.ServiceProvider.GetRequiredService<ICultureManager>())
    };
});

内容的提问来源于stack exchange,提问作者mihai921116

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 14:44:52