PropertyValidator 的自定义客户端验证问题

Issue with custom clientside validation for a PropertyValidator

FluentValidation 10.3.3,.NET 5

我有一个具有以下签名的自定义验证器:

public class FileSizeValidator<T> : PropertyValidator<T, IFormFile>

我尝试实现它的客户端部分,以便它与客户端部分已经工作的基于属性的验证具有同等地位。关于我将如何开始做这件事的线索很少,但我发现 this comment on an issue 似乎并没有那么过时。当然比我的搜索引导我的 Codeplex 更新。

所以我做了一个简单的客户端验证器,如下所示:

public class FileSizeClientValidator : ClientValidatorBase
{
    public FileSizeClientValidator(IValidationRule rule, IRuleComponent component) : base(rule, component)
    { }

    public override void AddValidation(ClientModelValidationContext context)
    {
        MergeAttribute(context.Attributes, "test-attribute", "test message");
    }
}

并用

注册
services
    .AddFluentValidation(options =>
    {
        options.ConfigureClientsideValidation(clientside =>
        {
            clientside.ClientValidatorFactories[typeof(FileSizeValidator<>)] = (_, rule, component) =>
                new FileSizeClientValidator(rule, component);
        });
    });

这似乎主要遵循上面链接的评论中包含的内容。无法准确地为我的验证器获取通用参数来转换它,因为似乎没有地方可以获取它,并且从那时起一些签名发生了变化,所以我决定进行更简单的测试。只是一个硬编码的属性和消息。

唉,表格里什么也没有显示。更糟糕的是,构造函数和 AddValidation 方法在任何时候都不会被命中,放置在那里的断点永远不会触发。

解决方案是使用非通用接口:

public interface IFileSizeValidator : IPropertyValidator
{
    public uint Max { get; }
}

由验证者实现

public class FileSizeValidator<T> : PropertyValidator<T, IFormFile>, IFileSizeValidator

以便它可以被客户端验证器使用:

public class FileSizeClientValidator : ClientValidatorBase
{
    public FileSizeClientValidator(IValidationRule rule, IRuleComponent component) : base(rule, component)
    { }

    public override void AddValidation(ClientModelValidationContext context)
    {
        var validator = (IFileSizeValidator)Validator;
        MergeAttribute(context.Attributes, "data-val", "true");
        MergeAttribute(context.Attributes, "data-val-filesize-max", validator.Max.ToString());
    }
}

并且还用于正确注册它:

services.AddFluentValidation(options =>
{
    options.RegisterValidatorsFromAssemblyContaining<Startup>();
    options.ConfigureClientsideValidation(clientside =>
    {
        clientside.ClientValidatorFactories[typeof(IFileSizeValidator)] = (_, rule, component) =>
            new FileSizeClientValidator(rule, component);
    });
})

完全归功于 this comment on Github that led me to the answer. I also described the whole process on dev.to 后代。