简体   繁体   English

如何将 FluentValidation 与 MetadataTypeAttribute 一起使用?

[英]How to use FluentValidation with MetadataTypeAttribute?

I'm developing ASP.NET MVC appliation.我正在开发 ASP.NET MVC 应用程序。 I've found Fluent Validation great validation tool and it works, but with my current architecture it has one drawback.我发现 Fluent Validation 是一个很棒的验证工具,而且它可以工作,但对于我当前的架构,它有一个缺点。 The validator does not care about Metadata.验证器不关心元数据。 I'm using Metadata on seperate class for clarity.为了清楚起见,我在单独的 class 上使用元数据。

Model Model

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

Metadata Model元数据 Model

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

Can anyone point a solution?谁能指出解决方案? I need data annotations for localization of labels (hence the DisplayAttribute).我需要用于标签本地化的数据注释(因此需要 DisplayAttribute)。

Think you need to write your own Display name resolver for fluent validation (guess this should be placed in your global.asax). 认为您需要编写自己的显示名称解析器以进行流畅的验证(猜测这应该放在您的global.asax中)。

Caution 警告

This solution is only trying to resolve the display name . 此解决方案仅尝试解析显示名称

Your other "validation" attributes ( Required , StringLength ) should no more be used, as you will manage that with FluentValidation. 您将不再使用其他“验证”属性( 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 ;
};

Personal point of view 个人观点

By the way, if you just use Metadata classes for clarity , don't use them ! 顺便说一句,如果您只是为了清晰起见使用Metadata类,请不要使用它们! It may be a solution if you have no choice (when entity classes are generated from an edmx and you really want to manage the display names this way), but I would really avoid them if it's not necessary. 如果您别无选择(当实体类是从edmx生成的,并且您确实想以这种方式管理显示名称时),这可能是一个解决方案,但是如果没有必要,我会真的避免使用它们。

public class CreateHireViewModel 
{
    [Display(Name = nameof(CreateHireViewModel.Title), ResourceType = typeof(Resource.HireResource.Hire))]
    public string Title { get; set; }
}

public class CreateHireViewModelValidator : AbstractValidator<CreateHireViewModel>
{
    public CreateHireViewModelValidator(IStringLocalizer<Resource.HireResource.Hire> l)
    {
        RuleFor(x => x.Title).NotEmpty().WithName(l[nameof(CreateHireViewModel.Title)]); 
        
        RuleFor(x => x.Title).Length(3, 50).WithName(l[nameof(CreateHireViewModel.Title)]);

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM