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