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

如何用ASP.Net Core 2.2与Westwind Globalization覆盖默认数据注解?

用Westwind Globalization覆盖ASP.NET Core 2.2数据注解的默认消息

针对你遇到的问题——想用Westwind Globalization从数据库加载资源替换StringLength这类数据注解的默认提示,同时解决ModelMetadataDetailsProviders的缓存问题,我有几个亲测有效的方案,适配ASP.NET Core 2.2的特性:


1. 放弃ModelMetadataDetailsProviders,改用自定义ValidationAttributeAdapterProvider

ModelMetadataDetailsProviders的核心问题是启动时一次性生成并缓存模型元数据,后续语言切换或数据库资源更新都不会触发重新加载,完全不符合你动态从数据库取资源的需求。

替代方案是自定义ValidationAttributeAdapterProvider——这个组件会在每次验证请求时被调用,能动态获取最新的本地化消息,完美避开缓存陷阱。

实现自定义适配器提供者

创建一个继承自默认ValidationAttributeAdapterProvider的类,注入Westwind的IStringResourceManager,然后针对需要替换的注解(比如StringLength、Required)动态设置错误消息:

public class LocalizedValidationAdapterProvider : ValidationAttributeAdapterProvider
{
    private readonly IStringResourceManager _resourceManager;

    // 注入Westwind的资源管理器
    public LocalizedValidationAdapterProvider(IStringResourceManager resourceManager)
    {
        _resourceManager = resourceManager;
    }

    public override IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
    {
        // 处理StringLengthAttribute,支持占位符替换
        if (attribute is StringLengthAttribute stringLengthAttr)
        {
            var localizedMsg = _resourceManager.GetString(
                "Validation_StringLength",
                new { Min = stringLengthAttr.MinimumLength, Max = stringLengthAttr.MaximumLength });

            if (!string.IsNullOrEmpty(localizedMsg))
            {
                stringLengthAttr.ErrorMessage = localizedMsg;
            }
        }
        // 处理RequiredAttribute(按需扩展Range、EmailAddress等其他注解)
        else if (attribute is RequiredAttribute requiredAttr)
        {
            var localizedMsg = _resourceManager.GetString("Validation_Required");
            if (!string.IsNullOrEmpty(localizedMsg))
            {
                requiredAttr.ErrorMessage = localizedMsg;
            }
        }

        // 调用默认逻辑完成适配器创建
        return base.GetAttributeAdapter(attribute, stringLocalizer);
    }
}

注册自定义适配器

在Startup.cs的ConfigureServices中,替换默认的适配器提供者,并配置Westwind使用数据库资源:

public void ConfigureServices(IServiceCollection services)
{
    // 注册自定义验证适配器
    services.AddSingleton<IValidationAttributeAdapterProvider, LocalizedValidationAdapterProvider>();

    // 配置Westwind Globalization使用数据库
    services.AddWestwindGlobalization(options =>
    {
        options.ResourceAccessMode = ResourceAccessMode.DbResourceManager;
        options.ConnectionString = Configuration.GetConnectionString("YourDatabase");
        options.ResourceTableName = "AppLocalizationResources"; // 你的数据库资源表名
        options.ResourceBaseName = "YourAppResources"; // 对应数据库中的ResourceSet字段
        options.AddMissingResources = false; // 禁止自动添加缺失资源(按需设置)
    });

    // 其他Mvc配置
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

2. 处理语言切换后的资源缓存

Westwind默认会缓存资源以提升性能,所以在切换语言时,需要主动清除缓存,确保下次请求能读取最新的数据库资源:

public IActionResult SwitchLanguage(string culture)
{
    // 设置语言Cookie
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    // 清除Westwind的资源缓存
    var resourceManager = HttpContext.RequestServices.GetRequiredService<IStringResourceManager>();
    resourceManager.ClearResourceCache();

    return Redirect(Request.Headers["Referer"].ToString());
}

3. 数据库资源表的注意事项

确保你的Westwind资源表中存在对应的键值对,比如:

  • 键名:Validation_StringLength,值:"字段长度必须在{Min}到{Max}字符之间"
  • 键名:Validation_Required,值:"此字段为必填项"

Westwind会自动根据当前文化(Culture)加载对应的资源行,无需手动处理多语言分支。


这种方案的核心是把消息的获取延迟到每次验证请求时,彻底避开模型元数据的缓存问题,同时完全利用Westwind Globalization的数据库资源管理能力,完美匹配你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:46:52