如何将 FluentValidation 与 MetadataTypeAttribute 一起使用?

How to use FluentValidation with MetadataTypeAttribute?

我正在开发 ASP.NET MVC 应用程序。我发现 Fluent Validation 是一个很棒的验证工具,而且它可以工作,但对于我当前的架构,它有一个缺点。验证器不关心元数据。为了清楚起见,我在单独的 class 上使用元数据。

型号

[MetadataType(typeof(DocumentEditMetadata))]
[Validator(typeof(DocumentValidator))]
public class DocumentEditModel
{
    public string DocumentNumber { get; set; }
    (etc...)
}

元数据模型

public class DocumentEditMetadata
{
    [Required]
    [StringLength(50)]
    [Display(ResourceType = typeof(Label), Name = "DocumentNumber")]
    public string DocumentNumber { get; set; }
    (etc...)
}

任何人都可以指出解决方案吗?我需要用于标签本地化的数据注释(因此需要 DisplayAttribute)。

认为您需要编写自己的显示名称解析器以进行流畅的验证(猜测这应该放在您的 global.asax 中)。

注意

此解决方案仅尝试解析显示名称

不应再使用您的其他 "validation" 属性(RequiredStringLength),因为您将使用 FluentValidation 对其进行管理。

ValidatorOptions.DisplayNameResolver = (type, memberInfo, expression) =>
{
      //this will get in this case, "DocumentNumber", the property name. 
      //If we don't find anything in metadata / resource, that what will be displayed in the error message.
      var displayName = memberInfo.Name;
      //we try to find a corresponding Metadata type
      var metadataType = type.GetCustomAttribute<MetadataTypeAttribute>();
      if (metadataType != null)
      {
           var metadata = metadataType.MetadataClassType;
           //we try to find a corresponding property in the metadata type
           var correspondingProperty = metadata.GetProperty(memberInfo.Name);
           if (correspondingProperty != null)
           {
                //we try to find a display attribute for the property in the metadata type
                var displayAttribute = correspondingProperty.GetCustomAttribute<DisplayAttribute>();
                if (displayAttribute != null)
                {
                     //finally we got it, try to resolve the name !
                     displayName = displayAttribute.GetName();
                }
          }
      }
      return displayName ;
};

个人观点

顺便说一下,如果您只是为了 清晰度 使用元数据 类,请不要使用它们! 如果您别无选择(当实体 类 是从 edmx 生成的并且您真的想以这种方式管理显示名称时),这可能是一个解决方案,但如果没有必要,我真的会避免使用它们。