https://github.com/simoncropp/extendedfluentvalidation
Extends FluentValidation with some more opinionated rules.
https://github.com/simoncropp/extendedfluentvalidation
Last synced: about 1 year ago
JSON representation
Extends FluentValidation with some more opinionated rules.
- Host: GitHub
- URL: https://github.com/simoncropp/extendedfluentvalidation
- Owner: SimonCropp
- License: mit
- Created: 2021-08-29T08:31:38.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2025-04-09T00:42:46.000Z (about 1 year ago)
- Last Synced: 2025-04-12T01:21:33.368Z (about 1 year ago)
- Language: C#
- Homepage:
- Size: 508 KB
- Stars: 16
- Watchers: 3
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- Funding: .github/FUNDING.yml
- License: license.txt
- Code of conduct: code_of_conduct.md
Awesome Lists containing this project
README
#
ExtendedFluentValidation
[](https://ci.appveyor.com/project/SimonCropp/ExtendedFluentValidation)
[](https://www.nuget.org/packages/ExtendedFluentValidation/)
Extends [FluentValidation](https://fluentvalidation.net/) with some more opinionated rules and extensions.
**See [Milestones](../../milestones?state=closed) 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`.
### Strings
String cannot be `String.Empty` or only white-space. The logic being: if the absence of text is valid, then make the member nullable. This helps since nullable is a first class strong type 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. The logic being: if the absence of any values is valid, then make the member nullable. This helps since nullable is a first class strong type 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`:
```cs
class PersonValidatorFromBase :
ExtendedValidator
{
public PersonValidatorFromBase()
{
//TODO: add any extra rules
}
}
```
snippet source | anchor
### AddExtendedRules
Using an extension method `AddExtendedRules`:
```cs
class PersonValidatorNonBase :
AbstractValidator
{
public PersonValidatorNonBase() =>
this.AddExtendedRules();
//TODO: add any extra rules
}
```
snippet source | anchor
### Equivalent
The above are equivalent to:
```cs
public class Person
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string? MiddleName { get; set; }
public string FamilyName { get; set; }
public DateTimeOffset Dob { get; set; }
}
```
snippet source | anchor
```cs
class PersonValidatorEquivalent :
AbstractValidator
{
public PersonValidatorEquivalent()
{
RuleFor(_ => _.Id)
.NotEqual(Guid.Empty);
RuleFor(_ => _.FirstName)
.NotEmpty();
RuleFor(_ => _.MiddleName)
.SetValidator(new NotWhiteSpaceValidator());
RuleFor(_ => _.FamilyName)
.NotEmpty();
RuleFor(_ => _.Dob)
.NotEqual(DateTimeOffset.MinValue);
}
}
```
snippet source | anchor
## Shared Rules
Given the following models:
```cs
public interface IDbRecord
{
public byte[] RowVersion { get; }
public Guid Id { get; }
}
public class Person :
IDbRecord
{
public Guid Id { get; set; }
public string Name { get; set; }
public byte[] 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:
```cs
[ModuleInitializer]
public static void Init() =>
ValidatorConventions.ValidatorFor()
.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.
```cs
class PersonValidator :
ExtendedValidator;
```
snippet source | anchor
The above is equivalent to:
```cs
class PersonValidatorEquivalent :
AbstractValidator
{
public PersonValidatorEquivalent()
{
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](https://thenounproject.com/term/pointed+star/802333/) designed by [Eliricon](https://thenounproject.com/mordarius/) from [The Noun Project](https://thenounproject.com).