This is a guide for passing custom objects to Fluent Validators. This can be helpful for more complex validation scenarios.
Here’s an example of what we want to achieve:
public class OurModelValidator: AbstractValidator<OurMVCViewModel>
{
public OurModelValidator(OurClassWeWantToPassToValidator ourClassWeWantToPassToValidator)
{
if (ourClassWeWantToPassToValidator.SomeCondition)
{
RuleFor(m => m.PropertyA).NotEmpty();
}
else
{
RuleFor(m => m.PropertyB).NotEmpty();
}
}
}
In order to achieve this, we need to make some changes to the FluentValidationModelValidatorProvider class by overriding its CreateValidator method:
public class OurCustomFluentModelValidatorProvider : FluentValidationModelValidatorProvider
{
protected override IValidator CreateValidator(ModelMetadata metadata, ControllerContext context)
{
var type = this.IsValidatingProperty(metadata) ? metadata.ContainerType : metadata.ModelType;
return GetOurModelValidator(type) ?? this.ValidatorFactory.GetValidator(type);
}
private IValidator GetOurModelValidator(Type modelType)
{
if (modelType == typeof(OurClassWeWantToPassToValidator))
{
var ourClassWeWantToPassToValidator = new OurClassWeWantToPassToValidator();
return new OurModelValidator(ourClassWeWantToPassToValidator);
}
return null;
}
}
Since we want FluentValidation to handle all situation when OurModelValidator is not applicable, we use built-in ValidatorFactory to return default Validator when validating anything but OurMVCViewModel.
And the last step is to register our new provider:
ModelValidatorProviders.Providers.Clear(); ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider()); ModelValidatorProviders.Providers.Add(new DataErrorInfoModelValidatorProvider()); ModelValidatorProviders.Providers.Add(new ClientDataTypeModelValidatorProvider()); ModelValidatorProviders.Providers.Add(new OurCustomFluentModelValidatorProvider());