如何为验证属性提供本地化的验证消息

Mat*_*tze 9 c# asp.net-core-mvc asp.net-core

我工作的一个ASP.NET的核心应用程序,我想覆盖的数据注解,像默认验证错误消息RequiredMinLengthMaxLength等我读的文档在ASP.NET核心全球化和本地化,它似乎是它没有涵盖我正在寻找的内容......

例如,Required属性的验证错误消息对于任何模型属性总是相同的。默认文本仅说明:{0} 字段是必需的,其中{0}占位符将填充属性的显示名称。

在我的视图模型中,我使用Required没有任何命名参数的属性,就像这样......

class ViewModel
{
    [Required, MinLength(10)]
    public string RequiredProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在我看来,设置ErrorMessageErrorMessageResourceName(和ErrorMessageResourceType)是不必要的开销。我想我可以实现类似于IDisplayMetadataProvider允许我为应用的属性返回错误消息的东西,以防验证失败。这可能吗?

jlc*_*vez 7

对于那些最终到达这里的人来说,为了寻找通用解决方案,解决它的最佳方法是使用验证元数据提供程序。我的解决方案基于这篇文章: AspNetCore MVC 错误消息,我使用了 .net 框架风格的本地化,并将其简化为使用设计的提供程序。

  1. 在你的项目中添加一个资源文件,例如ValidationsMessages.resx,并将访问修饰符设置为Internal 或Public,以便生成背后的代码,这将为您提供ResourceManager静态实例。
  2. 为每种语言的ValidationsMessages添加自定义本地化es .resx。请记住不要为此文件设置访问修饰符,代码是在步骤 1 中创建的。
  3. 添加IValidationMetadataProvider的实现
  4. 添加基于属性类型名称的本地化,如“RequiredAtrribute”。
  5. 在启动文件上设置您的应用程序。

示例验证消息。ES的.resx

在此处输入图片说明

IValidatioMetadaProvider 示例:

using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

public class LocalizedValidationMetadataProvider : IValidationMetadataProvider
{
    public LocalizedValidationMetadataProvider()
    {
    }

    public void CreateValidationMetadata(ValidationMetadataProviderContext context)
    {
        if (context.Key.ModelType.GetTypeInfo().IsValueType && Nullable.GetUnderlyingType(context.Key.ModelType.GetTypeInfo()) == null && context.ValidationMetadata.ValidatorMetadata.Where(m => m.GetType() == typeof(RequiredAttribute)).Count() == 0)
            context.ValidationMetadata.ValidatorMetadata.Add(new RequiredAttribute());
        foreach (var attribute in context.ValidationMetadata.ValidatorMetadata)
        {
            var tAttr = attribute as ValidationAttribute;
            if (tAttr?.ErrorMessage == null && tAttr?.ErrorMessageResourceName == null)
            {
                var name = tAttr.GetType().Name;
                if (Resources.ValidationsMessages.ResourceManager.GetString(name) != null)
                {
                    tAttr.ErrorMessageResourceType = typeof(Resources.ValidationsMessages);
                    tAttr.ErrorMessageResourceName = name;
                    tAttr.ErrorMessage = null;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

将提供程序添加到 Startup 类的 ConfigureServices 方法中:

services.AddMvc(options =>
{
     options.ModelMetadataDetailsProviders.Add(new LocalizedValidationMetadataProvider());
})
Run Code Online (Sandbox Code Playgroud)


Tse*_*eng 4

如果要更改完整文本,则应使用资源文件对其进行本地化。

每个都有和ValidationAttribute的属性(请参阅此处的源代码)。ErrorMessageResourceTypeErrorMessageResourceName

[Required(ErrorMessageResourceName = "BoxLengthRequired", ErrorMessageResourceType = typeof(SharedResource))]
Run Code Online (Sandbox Code Playgroud)

更新

好吧,似乎有一种方法可以使用本地化提供程序来对其进行本地化,但它仍然有点老套,并且需要属性上至少有一个属性(来自这篇博客文章- 不过警告的话,它最初是针对旧的 RC1或 RC2 版本。它应该可以工作,但该文章中的某些 API 可能无法工作):

启动时:

services.AddMvc()
   .AddViewLocalization()
   .AddDataAnnotationsLocalization();
Run Code Online (Sandbox Code Playgroud)

在你的模型上:

[Required(ErrorMessage = "ViewModelPropertyRequired"), MinLength(10, ErrorMessage = "ViewModelMinLength")]
public string RequiredProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

并实现/使用使用数据库的本地化提供程序(即https://github.com/damienbod/AspNet5Localization)。

  • 好的,但是如果我不想使用资源文件而是数据库怎么办?除此之外,我想避免更多的争论。 (2认同)