AddValidation() extension method performs registration of validation provider service and validators implementing IValidator or inherited from Validator class.
Parameter name
Parameter type
Description
assembliesToScan
params Assembly[]
List of assemblies to search validators.
configureOptions
Action<ValidationServiceOptions>
Options to be used by validation service.
Additionally configure IValidationProvider service by specifying it's type and lifetime used ValidationServiceOptions.
Property name
Property type
Description
ProviderServiceType
Type
Changes standard implementation of IValidationProvider to specified one, default is typeof(ValidationProvider).
ProviderServiceLifetime
ServiceLifetime
Specifies the lifetime of an IValidationProvider service, default is Transient.
Usage
Validation objects can be Entities, DTO's, Commands, Queries and many others typed objects.
The basic usage is:
publicrecordUserCreateCommand:IOperation<int>{publicstring Email { get; init; }publicstring Password { get; init; }}publicclassUserCreateCommandValidator:IValidator<UserCreateCommand>{privatereadonlyIDbContext _dbContext;publicUserCreateCommandValidator(IDbContext dbContext)=> _dbContext = dbContext;publicasyncTask<ValidationResult> ValidateAsync(UserCreateCommand command,CancellationToken cancellationToken) {var failures =newList<ValidationFailure>();if (string.IsNullOrWhitespace(command.Email)) {failures.Add(newValidationFailure(nameof(command.Email),command.Email,"Email is required.")); }if (IsValidEmail(command.Email) ==false) {failures.Add(newValidationFailure(nameof(command.Email),command.Email,"Email is invalid.")); }bool isUniqueEmail =awaitIsUniqueEmailAsync(command.Email, cancellationToken);if (isUniqueEmail ==false) {failures.Add(newValidationFailure(nameof(command.Email),command.Email,"Email is not unique.")); }if (string.IsNullOrWhitespace(command.Password)) {failures.Add(newValidationFailure(nameof(command.Password),command.Password,"Password is required.")); }if (IsValidPassword(command.Password) ==false) {failures.Add(newValidationFailure(nameof(command.Password),command.Password,"Password is invalid.")); }returnfailures.ToValidationResult(); }privateboolIsValidEmail(string email) {/* Some logic here */ }privateasyncTask<bool> IsUniqueEmailAsync(string email,CancellationToken cancellationToken)=>await_dbContext.Users.AnyAsync(x =>x.Email== email, cancellationToken) ==false;privateboolIsValidPassword(string password) {/* Some logic here */ }}
The last step is to inject IValidationProvider service and use it:
publicclassUserCreateCommandHandler:IOperationHandler<UserCreateCommand,int>{privatereadonlyIDbContext _dbContext;privatereadonlyIValidationProvider _validationProvider;publicUserCreateCommandHandler(IDbContext dbContext,IValidationProvider validationProvider) { _dbContext = dbContext; _validationProvider = validationProvider; }publicasyncTask<Guid> HandleAsync(UserCreateCommand command,CancellationToken cancellationToken) { // Validate incoming command and throw exception if failures.await_validationProvider.ValidateAndThrowAsync(command);/* Some logic here */ }}
Recommendation: For validating Commands/Queries use IOperationFilter instead of calling _validationProvider.ValidateAndThrowAsync() in each command/query. See more details about Operations.
IValidationProvider methods:
Method name
Return type
Description
ValidateAsync
ValidationResult
Asynchronously validates the object and returns the ValidationResult.
ValidateAndThrowAsync
-
Asynchronously validates the object and throws ValidationException if validation result has failures.
ValidationFailure represents a single validation error.
ValidationFailure properties:
Property name
Property type
Description
ParameterName
string
The name of the parameter that caused the failure.
ActualValue
object
The value of the parameter that caused the failure.
Message
string
The message that describes the failure.
Code
string
The optional failure code.
Level
ValidationFailureLevel
The optional level of failure - Error, Warning or Info. Default value is Error.
ValidationResult represents all failures that occur during validation execution.
ValidationResult properties:
Property name
Property type
Description
IsValid
bool
Returns true if the validation result has not failures, otherwise false.
ValidationResult class inherits from IEnumerable<ValidationFailure> and allow you to use iteration:
ValidationResult validationResult =await_validationProvider.ValidateAsync(command);if (validationResult.IsValid==false){foreach(ValidationFailure validationFailure in validationResult) {_logger.LogError(validationFailure.Message); }}
Thrown ValidationException class has following main properties:
Property name
Property type
Description
ValidationResult
ValidationResult
The result of validation.
Message
string
The messages of all failures joined into one string.
try{await_validationProvider.ValidateAsync(command);}catch(ValidationException ex){ // Option 1 - Use default exception message property:_logger.LogError(ex.Message); // Option 2 - Iterate all failures with message:foreach(ValidationFailure validationFailure inex.ValidationResult) {_logger.LogError(validationFailure.Message); }}