The clientside part of a custom PropertyValidator doesn't run
Closed this issue · 2 comments
FluentValidation version
10.3.3
ASP.NET version
.NET 5
Summary
I have a custom validator with the following signature:
public class FileSizeValidator<T> : PropertyValidator<T, IFormFile>
and I tried to implement the client-side portion of it, so that it has parity with attribute-based validations where the client-side portion already worked. There's precious few leads on how would I ever start doing it, but I found #1314 (comment) which seemed not even all that outdated. Certainly more recent then Codeplex where my search led me.
So I made a simple client-side validator like so:
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");
}
}
and registered it with
services
.AddFluentValidation(options =>
{
options.ConfigureClientsideValidation(clientside =>
{
clientside.ClientValidatorFactories[typeof(FileSizeValidator<>)] = (_, rule, component) =>
new FileSizeClientValidator(rule, component);
});
});
which seems to mostly follow what was contained in the comment linked above. Can't exactly get the generic parameter for my validator to cast it, because there seems to be nowhere to get it from, and some signatures changed since then, so I decided on a simpler test. Just a hardcoded attribute and message.
Alas, nothing shows up in the form. Worse still, neither the constructor nor the AddValidation
method get hit at any point, the breakpoints placed there never trigger.
Steps to Reproduce
- Copy the code from summary
- Try to use it with a custom generic validator inheriting
PropertyValidator<T1, T2>
Hi, you're on the right track.
Can't exactly get the generic parameter for my validator to cast it,
You should ensure your validator has a non-generic interface, and use that as the key. For example, our NotNullValidator<T,TProperty>
implements a non-generic INotNullValidator
marker interface: https://github.com/FluentValidation/FluentValidation/blob/main/src/FluentValidation/Validators/NotNullValidator.cs
This is then used in the client validator factories as the key:
Thanks, the non-generic interface was the missing piece!