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 后代。
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 后代。