asp.net 如何将FluentValidation与元数据类型属性结合使用?

uhry853o  于 2022-12-01  发布在  .NET
关注(0)|答案(2)|浏览(149)

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

型号

[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)。

bis0qfac

bis0qfac1#

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

注意事项

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

不应再使用其他“验证”属性(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生成的,并且您确实希望以这种方式管理显示名称时),这可能是一种解决方案,但如果没有必要,我确实会避免使用它们。

rhfm7lfc

rhfm7lfc2#

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)]);

    }
}

相关问题