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

.NET Core 2.0数据注解本地化切换异常问题求助

解决.NET Core 2.0运行时切换语言后数据注解不更新的问题

这个问题我之前也碰到过,核心原因在于**.NET Core 2.0中数据注解的本地化元数据默认是全局缓存的**——模型元数据在第一次请求时就被创建并缓存,后续请求不会根据当前文化重新生成,所以切换语言后,数据注解的翻译还是用的缓存里的旧文化内容;而@Localizer["...."]是每次请求都会从资源文件里读取当前文化的对应值,所以能正常切换。

下面是具体的解决步骤:

1. 自定义模型元数据提供器,让缓存键包含当前文化

创建一个继承自DataAnnotationsModelMetadataProvider的类,重写相关方法,把当前请求的文化名称加入到缓存键中,这样不同文化下的模型元数据会被分别缓存:

using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using System.Globalization;
using System.Collections.Concurrent;

public class CultureAwareDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<object> attributes,
        Type containerType,
        Type modelType,
        string propertyName)
    {
        var metadata = base.CreateMetadata(attributes, containerType, modelType, propertyName);
        // 将当前文化名称加入元数据附加信息,辅助缓存区分
        metadata.AdditionalValues["Culture"] = CultureInfo.CurrentUICulture.Name;
        return metadata;
    }

    // 重写类型元数据获取方法,用包含文化的键缓存
    public override ModelMetadata GetMetadataForType(Type modelType)
    {
        var cacheKey = $"{modelType.FullName}_{CultureInfo.CurrentUICulture.Name}";
        if (ModelMetadataCache.TryGetValue(cacheKey, out var metadata))
        {
            return metadata;
        }
        metadata = base.GetMetadataForType(modelType);
        ModelMetadataCache.TryAdd(cacheKey, metadata);
        return metadata;
    }

    // 重写属性元数据获取方法,用包含文化的键缓存
    public override ModelMetadata GetMetadataForProperty(Type containerType, Type modelType, string propertyName)
    {
        var cacheKey = $"{containerType.FullName}.{propertyName}_{CultureInfo.CurrentUICulture.Name}";
        if (ModelMetadataCache.TryGetValue(cacheKey, out var metadata))
        {
            return metadata;
        }
        metadata = base.GetMetadataForProperty(containerType, modelType, propertyName);
        ModelMetadataCache.TryAdd(cacheKey, metadata);
        return metadata;
    }

    // 用线程安全字典实现文化区分的缓存
    private static readonly ConcurrentDictionary<string, ModelMetadata> ModelMetadataCache = new ConcurrentDictionary<string, ModelMetadata>();
}

2. 在Startup.cs中替换默认的模型元数据提供器

在ConfigureServices方法里,注册我们自定义的提供器,替换掉默认的DataAnnotationsModelMetadataProvider:

public void ConfigureServices(IServiceCollection services)
{
    // 配置本地化资源路径
    services.AddLocalization(options => options.ResourcesPath = "Resources");

    services.AddMvc()
        .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
        .AddDataAnnotationsLocalization()
        // 替换默认模型元数据提供器
        .AddMvcOptions(options =>
        {
            options.ModelMetadataDetailsProviders.Add(new CultureAwareDataAnnotationsModelMetadataProvider());
        });

    // 设置支持的文化列表
    services.Configure<RequestLocalizationOptions>(options =>
    {
        var supportedCultures = new[]
        {
            new CultureInfo("en"),
            new CultureInfo("fr")
        };

        options.DefaultRequestCulture = new RequestCulture("en");
        options.SupportedCultures = supportedCultures;
        options.SupportedUICultures = supportedCultures;
    });
}

3. 确保语言切换时正确更新当前文化

切换语言的动作要确保更新HttpContext的文化,并且把新的文化保存到Cookie里,这样后续请求会使用新的文化:

public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    return LocalRedirect(returnUrl);
}

额外注意点

  • 如果你项目里用了IMemoryCache,可以把自定义提供器里的字典缓存换成IMemoryCache,这样能更好地利用框架的缓存机制,也方便设置过期策略。
  • 测试时要确认资源文件命名规范,比如模型的数据注解翻译文件应该是Resources/YourModelName.fr.resx(对应法语),确保资源文件能被正确读取。

这样修改后,运行时切换语言时,数据注解的翻译就会跟着当前文化更新了——因为每个文化都有独立的模型元数据缓存,切换文化后会读取对应文化的缓存(如果没有就重新生成)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:11:43