Skip to content

Repository files navigation

ExtendedFluentValidation

Build statusNuGet Status

Extends FluentValidation with some more opinionated rules and extensions.

See Milestones for release notes.

Nuget

https://nuget.org/packages/ExtendedFluentValidation/

Extra Rules

Nullability

It leverages nullability information to make all non-nullable reference properties to be required.

Dates

DateTime, DateTimeOffset, and DateOnly cannot be MinValue. Reason: if the absence of a value is valid, then make the member nullable.

Strings

String cannot be String.Empty or only white-space. Reason: if the absence of text is valid, then make the member nullable. This helps since nullable is a first class strong typed feature, where "string is empty or only white-space" is a runtime check.

Guids

Guids cannot be Guid.Empty.

Lists/Collections

Lists and Collection cannot be empty if ValidatorConventions.ValidateEmptyLists() is called in a module initializer. Reason: if the absence of any values is valid, then make the member nullable. This helps since nullable is a first class strong typed feature, where "list contains no values" is a runtime check.

Usage

There are two ways of applying the extended rules.

ExtendedValidator

Using a base class ExtendedValidator:

classPersonValidatorFromBase:ExtendedValidator<Person>{publicPersonValidatorFromBase(){//TODO: add any extra rules}}

snippet source | anchor

AddExtendedRules

Using an extension method AddExtendedRules:

classPersonValidatorNonBase:AbstractValidator<Person>{publicPersonValidatorNonBase()=>this.AddExtendedRules();//TODO: add any extra rules}

snippet source | anchor

Equivalent

The above are equivalent to:

publicclassPerson{publicGuidId{get;set;}publicstringFirstName{get;set;}publicstring?MiddleName{get;set;}publicstringFamilyName{get;set;}publicDateTimeOffsetDob{get;set;}}

snippet source | anchor

classPersonValidatorEquivalent:AbstractValidator<Person>{publicPersonValidatorEquivalent(){RuleFor(_ =>_.Id).NotEqual(Guid.Empty);RuleFor(_ =>_.FirstName).NotEmpty();RuleFor(_ =>_.MiddleName).SetValidator(newNotWhiteSpaceValidator<Person>());RuleFor(_ =>_.FamilyName).NotEmpty();RuleFor(_ =>_.Dob).NotEqual(DateTimeOffset.MinValue);}}

snippet source | anchor

Shared Rules

Given the following models:

publicinterfaceIDbRecord{publicbyte[]RowVersion{get;}publicGuidId{get;}}publicclassPerson:IDbRecord{publicGuidId{get;set;}publicstringName{get;set;}publicbyte[]RowVersion{get;set;}}

snippet source | anchor

It is desirable to have the rules for IDbRecord defined separately, and not need to duplicate them for every implementing class. This can be done using shares rules.

Configure any shared rules at startup:

[ModuleInitializer]publicstaticvoidInit()=>ValidatorConventions.ValidatorFor<IDbRecord>().RuleFor(record =>record.RowVersion).Must(rowVersion =>rowVersion?.Length==8).WithMessage("RowVersion must be 8 bytes");

snippet source | anchor

The PersonValidator used only the standard rules, so needs no constructor.

classPersonValidator:ExtendedValidator<Person>;

snippet source | anchor

The above is equivalent to:

classPersonValidatorEquivalent:AbstractValidator<Person>{publicPersonValidatorEquivalent(){RuleFor(_ =>_.Id).NotEqual(Guid.Empty);RuleFor(_ =>_.Name).NotEmpty();RuleFor(_ =>_.RowVersion).NotNull().Must(rowVersion =>rowVersion?.Length==8).WithMessage("RowVersion must be 8 bytes");}}

snippet source | anchor

Icon

Pointed Star designed by Eliricon from The Noun Project.

About

Extends FluentValidation with some more opinionated rules.

Resources

Code of conduct

Stars

18 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages