I have the following validator class:
public class FranchiseInfoValidator : AbstractValidator<FranchiseInfo>
{
public FranchiseInfoValidator()
{
RuleFor(franchiseInfo => franchiseInfo.FolderName).NotEmpty().Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters");
RuleFor(franchiseInfo => franchiseInfo.ExeIconName).NotEmpty().Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters");
RuleFor(franchiseInfo => franchiseInfo.FullName).NotEmpty().Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters");
RuleFor(franchiseInfo => franchiseInfo.ShortName).NotEmpty().Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters");
}
NotEmpty() and Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters") validators with the custom message are the same for all properties. Is it possible to group them in one custom validator and then write something like this:
RuleFor(franchiseInfo => franchiseInfo.FolderName).SetValidator(new CustomValidator());
I have done some custom validators but not in this scenario. Is this possible? I have found no such example in the documentation. Furthermore, I wonder if this is possible to be done generic so if I have another validator class with properties to apply the same custom validator? Thanks.
yes, it should work with something like that
public class MyCustomValidator : PropertyValidator
{
public MyCustomValidator()
: base("Property {PropertyName} has invalid characters.")
{
}
protected override bool IsValid(PropertyValidatorContext context)
{
var element = context.PropertyValue as string;
return !string.IsNullOrEmpty(element) && Regex.IsMatch(element, "^[a-zA-Z0-9_.:-]+$");
}
}
usage :
with your code, or create your own extension
public static class MyValidatorExtensions {
public static IRuleBuilderOptions<T, string> CheckIfNullAndMatches<T>(this IRuleBuilder<T, string> ruleBuilder) {
return ruleBuilder.SetValidator(new MyCustomValidator<TElement>());
}
}
then usage would be
RuleFor(franchiseInfo => franchiseInfo.FolderName).CheckIfNullAndMatches();
You could also have a regex as a parameter, if you need a more generic validator...
doc here
Related
public class Validator : AbstractValidator<Command>
{
public Validator(ICheckExists<ICheckEntityExists> checkEntityExists)
{
RuleFor(x => x)
.EntityDoesNotExist(checkEntityExists, c => new CheckEntityExists()
{
TypeId = c.Id,
StatusId = c.StatusId
});
}
Hi, I Have a problem. The code above generates "must not exist" error message.
EntityDoesNotExist is an extension method that I can not change.Since it is an extension method I could not use any of this OverridePropertyName WithName WithMessage.
The question is how can I change the error message to a custom one.
I have written this code which does the thing
ValidatorOptions.Global.DisplayNameResolver = (type, member, expression) =>
{
if (member == null)
{
return "Hello world";
}
return member.Name;
};
But it works only if I have 1 rule that has no name and it looks not pretty.
Maybe there it is another way of achieving the same result?
The problem is that extension method you are using return an instance of IRuleBuilder<T, out TProperty> interface which doesn't contain definitions for method like WithMessage. This and other methods you mentioned are extension methods for IRuleBuilderOptions<T, TProperty> interface which inherits IRuleBuilder<T, out TProperty>.
So one of possible solutions is to wrap EntityDoesNotExist extension method into another method which will downcast the returned type to IRuleBuilderOptions<T, TProperty>
For example we have class called Person:
public class Person
{
public string Name { get; set; } = null!;
}
Extension method for Name property which returns IRuleBuilder type:
public static IRuleBuilder<T, string> ValidateNameLength<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.Must(name => name.Length < 5).WithMessage("Incorrect length");
}
So we can wrap this method something like this:
public static IRuleBuilderOptions<T, string> ValidateNameLengthWrapper<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return (IRuleBuilderOptions<T, string>) ruleBuilder.ValidateNameLength();
}
Then we can use WithMessage method to override error description:
public class Validator : AbstractValidator<Person>
{
public Validator()
{
CascadeMode = CascadeMode.Continue;
RuleFor(x => x.Name!).ValidateNameLengthWrapper().WithMessage("Name must be less than 5 characters");
}
}
But maybe would be better to write your own extension method or resolve the problem outside the validation context.
Is the below code achievable?
If not, is there a similar approach to get child properties through methods in same class.
The reason to do it this was is to check for null and at the same time avoid creating multiple mapping profiles. Please guide me to the right direction on this one. Thanks
Its giving me this error:
Client projection contains reference to constant expression of 'Project.Web.Dto.Mapper.ProviderMappingProfile' through instance method 'GetLastUpdate'. This could potentially cause memory leak. Consider making the method static so that it does not capture constant in the instance.
{
public ProviderMappingProfile ()
{
CreateMap<Provider, ProviderDto>(MemberList.Destination)
.ForMember(d => d.property1, opts => opts.MapFrom(s => GetLastUpdate(s)))
.ForMember(d => d.property2, opts => opts.MapFrom(s => GetPropertChild2(s)));
}
private DateTime? GetLastUpdate(Provider provider)
{
var LastUpdate = provider.childDetails?.FirstOrDefault().LastUpdate;
return LastUpdate;
}
private string GetPropertChild2(Provider provider)
{
if (provider.IsCombined)
{
return provider.CombinedNo;
}
return provider.Worker?.Work;
}
}
You should refactor your Get... methods into custom resolvers:
public class LastUpdateResolver : IValueResolver<Provider, ProviderDto, DateTime?>
{
public DateTime? Resolve(Provider source, ProviderDto destination, DateTime? member, ResolutionContext context)
{
return source.childDetails?.FirstOrDefault().LastUpdate;
}
}
and use it on the profile declaration:
.ForMember(d => d.property1, opts => opts.MapFrom<LastUpdateResolver>())
I have a class with a collection that needs validation. The generic on the collection takes an interface and different types can be added to the collection.
What is the cleanest path forward to creating a FluentValidation validator that supports polymorphism?
public interface IWizardStep {}
public class WizardOne : IWizardStep
{
public string Model { get; set; }
}
public class WizardTwo : IWizardStep
{
public string FirstName { get; set; }
}
public class Wizard
{
public Wizard()
{
var w1 = new WizardOne();
var w2 = new WizardTwo();
Steps = new List<IWizardStep>
{
w1,
w2
};
}
public IList<IWizardStep> Steps { get; set; }
}
public class WizardValidator : AbstractValidator<Wizard>
{
public WizardValidator()
{
RuleFor(x => x.Steps)
// Steps First where is WizardOne
// Model.NotEmpty()
// Steps First where is WizardTwo
// FirstName.NotEmpty()
}
FluentValidation doesn't support polymorphism for child collections like this out of the box, but you can add this behaviour by using a custom property validator, or by using OfType in your rule definitions.
I've written about both approaches before here:
Step 1: Create a validator for each implementor
Start by creating a validator for WizardOne and WizardTwo:
public class WizardOneValidator : AbstractValidator<WizardOne> {
public WizardOneValidator() {
RuleFor(x => x.Model).NotEmpty();
}
}
public class WizardTwoValidator : AbstractValidator<WizardTwo> {
public WizardTwoValidator() {
RuleFor(x => x.FirstName).NotEmpty();
}
}
Step 2: Create the parent validator
You have two options for defining the parent validator. The simplest approach is to use OfType, but this is less performant. The more complex option is to use a custom property validator.
Option 1: Using OfType
public WizardValidator : AbstractValidator<Wizard> {
public WizardValidator() {
RuleForEach(x => x.Steps.OfType<WizardOne>()).SetValidator(new WizardOneValidator());
RuleForEach(x => x.Steps.OfType<WizardTwo>()).SetValidator(new WizardTwoValidator());
}
}
This is the simplest approach, but calling OfType inside the call RuleFor will end up bypassing FluentValidation's expression cache, which is a potential performance hit. It also iterates the collection multiple. This may or may not be an issue for you - you'll need to decide if this has any real-world impact on your application.
Option 2: Using a custom PropertyValidator.
This uses a custom custom validator which can differentiate the underlying type at runtime:
public WizardValidator : AbstractValidator<Wizard> {
public WizardValidator() {
RuleForEach(x => x.Steps).SetValidator(new PolymorphicValidator<Wizard, IWizardStep>()
.Add<WizardOne>(new WizardOneValidator())
.Add<WizardTwo>(new WizardTwoValidator())
);
}
}
Syntactically, this isn't quite as nice, but doesn't bypass the expression cache and doesn't iterate the collection multiple times. This is the code for the PolymorphicValidator:
public class PolymorphicValidator<T, TInterface> : ChildValidatorAdaptor<T, TInterface> {
readonly Dictionary<Type, IValidator> _derivedValidators = new Dictionary<Type, IValidator>();
// Need the base constructor call, even though we're just passing null.
public PolymorphicValidator() : base((IValidator<TInterface>)null, typeof(IValidator<TInterface>)) {
}
public PolymorphicValidator<T, TInterface> Add<TDerived>(IValidator<TDerived> derivedValidator) where TDerived : TInterface {
_derivedValidators[typeof(TDerived)] = derivedValidator;
return this;
}
public override IValidator<TInterface> GetValidator(PropertyValidatorContext context) {
// bail out if the current item is null
if (context.PropertyValue == null) return null;
if (_derivedValidators.TryGetValue(context.PropertyValue.GetType(), out var derivedValidator)) {
return new ValidatorWrapper(derivedValidator);
}
return null;
}
private class ValidatorWrapper : AbstractValidator<TInterface> {
private IValidator _innerValidator;
public ValidatorWrapper(IValidator innerValidator) {
_innerValidator = innerValidator;
}
public override ValidationResult Validate(ValidationContext<TInterface> context) {
return _innerValidator.Validate(context);
}
public override Task<ValidationResult> ValidateAsync(ValidationContext<TInterface> context, CancellationToken cancellation = new CancellationToken()) {
return _innerValidator.ValidateAsync(context, cancellation);
}
public override IValidatorDescriptor CreateDescriptor() {
return _innerValidator.CreateDescriptor();
}
}
}
This will probably be implemented in the library as a first class feature at some point in the future - you can track its development here if you're interested.
I'm trying to apply FluentValidation (v 9.1.1) on a tree structure, using the visitor pattern. The special thing about it is, that a couple of different tree elements all implement an interface and the child properties of the elements are of this interface type. In other words, the child properties are not strongly typed. Simplified model see below. Each validator goes on the specific implementation and I don't get the point, how to attach child validators for interface children.
Here is a demo model (working code):
public interface IElement
{
Type ResultType { get; }
TResult Accept<TResult>(IElementVisitor<TResult> visitor);
}
public class ConstElement : IElement
{
public object Value { get; set; }
public Type ResultType => Value?.GetType();
public TResult Accept<TResult>(IElementVisitor<TResult> visitor)
{
return visitor.VisitElement(this);
}
}
public class BinaryElement : IElement
{
// Child properties are not strongly typed.
public IElement Left { get; set; }
public IElement Right { get; set; }
public Operand Operand { get; set; }
public Type ResultType => Operand switch
{
Operand.Equal => typeof(bool),
Operand.GreaterThan => typeof(bool),
Operand.Plus => Left.GetType(),
Operand.Multiply => Left.GetType(),
_ => throw new NotImplementedException(),
};
public TResult Accept<TResult>(IElementVisitor<TResult> visitor)
{
return visitor.VisitElement(this);
}
}
public enum Operand { Equal, GreaterThan, Plus, Multiply }
public class ConstElementValidator : AbstractValidator<ConstElement>
{
public ConstElementValidator()
{
RuleFor(ele => ele.Value).NotNull().Must(value => (value is double) || (value is TimeSpan));
}
}
public class BinaryElementValidator : AbstractValidator<BinaryElement>
{
public BinaryElementValidator()
{
// Rules for the element itself
RuleFor(ele => ele.Left).NotNull();
RuleFor(ele => ele.Right).NotNull();
RuleFor(ele => ele).Must(ele => IsValidResultTypeCombination(ele.Left.ResultType, ele.Right.ResultType, ele.Operand));
// Add rules for child elements here? How?
}
private bool IsValidResultTypeCombination(Type left, Type right, Operand operand)
{
if (left == typeof(bool) && right != typeof(bool))
return false;
// other result type validations...
return true;
}
}
public interface IElementVisitor<TResult>
{
TResult VisitElement(ConstElement element);
TResult VisitElement(BinaryElement element);
}
public class ValidationVisitor : IElementVisitor<ValidationResult>
{
public ValidationResult VisitElement(ConstElement element)
{
return new ConstElementValidator().Validate(element);
}
public ValidationResult VisitElement(BinaryElement element)
{
// How to add validation of element.Left and element.Right,
// taking into account, that their type is IElement, while Validators are bound to the implementation type?
var result = new BinaryElementValidator().Validate(element);
var leftResult = element.Left.Accept(this);
var rightResult = element.Right.Accept(this);
// merge leftResult and rightResult with result
return result;
}
}
In general, there are two ways to add child validation. Either calling child validators directly in the validators, which would make the ValidationVisitor obsolete, or let focus the validators on their own logic and adding child validation in the ValidationVisitor, as shown in the code.
The only way I am able to proceed right now is by using the visitor and merging the validation results of an element and its child elements.
Is there a way to add child validators to the BinaryElement in this scenario? Either in the visitor or in the BinaryElementValidator directly.
There's a couple of different ways to do this. You can either define multiple rules for each of the interface implementors, or you can use a custom property validator to do runtime inspection on the type. This is similar to this answer.
Option 1: Multiple rule definitions with a type filter
With this option, you create a specific rule definition for each potential implementor of the interface:
// Inside your BinaryElementValidator use a safe cast inside the RuleFor definition.
// If it isn't the right type, the child validator won't be executed
// as child validators aren't run for null properties.
RuleFor(x => x.Left as BinaryElement).SetValidator(new BinaryElementValidator());
RuleFor(x => x.Left as ConstElement).SetValidator(new ConstElementValidator());
RuleFor(x => x.Right as BinaryElement).SetValidator(new BinaryElementValidator());
RuleFor(x => x.Right as ConstElement).SetValidator(new ConstElementValidator());
This is the simplest approach, but by having a more complex expression within the call to RuleFor you will be bypassing FluentValidation's expression cache, which will be a performance hit if you're instantiating the validator many times. I'll leave it for you to decide if that would be an issue in your application.
You may need to call OverridePropertyName for each rule too, as FluentValidation won't be able to infer the name of the property with this approach.
Option 2: A custom property validator
A slightly more complex solution, but means you can stick with simple property expressions inside RuleFor, meaning you won't bypass the cache. This makes use of a custom validator called PolymorphicValidator, which will inspect the type of the property at runtime.
RuleFor(x => x.Left).SetValidator(new PolymorphicValidator<BinaryElement, IElement>()
.Add<BinaryElement>(new BinaryElementValidator())
.Add<ConstElement>(new ConstElementValidator())
);
RuleFor(x => x.Right).SetValidator(new PolymorphicValidator<BinaryElement, IElement>()
.Add<BinaryElement>(new BinaryElementValidator())
.Add<ConstElement(new ConstElementValidator())
);
And here's the code for the PolymorphicValidator:
public class PolymorphicValidator<T, TInterface> : ChildValidatorAdaptor<T, TInterface> {
readonly Dictionary<Type, IValidator> _derivedValidators = new Dictionary<Type, IValidator>();
// Need the base constructor call, even though we're just passing null.
public PolymorphicValidator() : base((IValidator<TInterface>)null, typeof(IValidator<TInterface>)) {
}
public PolymorphicValidator<T, TInterface> Add<TDerived>(IValidator<TDerived> derivedValidator) where TDerived : TInterface {
_derivedValidators[typeof(TDerived)] = derivedValidator;
return this;
}
public override IValidator<TInterface> GetValidator(PropertyValidatorContext context) {
// bail out if the current item is null
if (context.PropertyValue == null) return null;
if (_derivedValidators.TryGetValue(context.PropertyValue.GetType(), out var derivedValidator)) {
return new ValidatorWrapper(derivedValidator);
}
return null;
}
private class ValidatorWrapper : AbstractValidator<TInterface> {
private IValidator _innerValidator;
public ValidatorWrapper(IValidator innerValidator) {
_innerValidator = innerValidator;
}
public override ValidationResult Validate(ValidationContext<TInterface> context) {
return _innerValidator.Validate(context);
}
public override Task<ValidationResult> ValidateAsync(ValidationContext<TInterface> context, CancellationToken cancellation = new CancellationToken()) {
return _innerValidator.ValidateAsync(context, cancellation);
}
public override IValidatorDescriptor CreateDescriptor() {
return _innerValidator.CreateDescriptor();
}
}
}
This approach is actually going to be added to the library in a future version - you can track its development here if you're interested: https://github.com/FluentValidation/FluentValidation/issues/1237
public class MyObjectMap : IAutoMappingOverride<MyObject>
{
public void Override(AutoMapping<MyObject> mapping)
{
mapping.IgnoreProperty(x => x.InterfaceProperty);
}
}
I am currently doing this in every map... how can I make this into a convention? I am adding conventions like so:
private Action<IConventionFinder> GetConventions()
{
return c =>
{
c.Add<ForeignKeyConvention>();
c.Add<HasManyConvention>();
c.Add<HasManyToManyConvention>();
c.Add<ManyToManyTableNameConvention>();
c.Add<PrimaryKeyConvention>();
c.Add<ReferenceConvention>();
c.Add<TableNameConvention>();
};
}
I think this is not something related to Convention,however it is subject to Mapping Overriding, try this:
public class AutoMapDefaultConfig : DefaultAutomappingConfiguration
{
public override bool ShouldMap(FluentNHibernate.Member member)
{
if (member.Name == "InterfaceProperty")
return false;
return base.ShouldMap(member);
}
}
i haven't try this actually, but I think it may help,and notice that the DefaultAutomappingConfiguration is in Fluent-NHibernate V1.1