NuGet - FluentValidation

The FluentValidation is used for bulding validation rules.

Here is a website home page:
https://docs.fluentvalidation.net/en/latest/

It’s a nice website, gives good examples and is a fairly easy read.

Basically you install the library via nuget, then create a class to hold validators, and then hook that class into your software.

This page includes a summary of validators built into the library. Of course there are ways to create your own rules.
https://docs.fluentvalidation.net/en/latest/built-in-validators.html

Sample

Here is a Note Entity object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace Note.Domain.Entities
{
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

public class NoteEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public DateTime Dt { get; set; }
public string Who { get; set; }
public long NoteTypeId { get; set; }
public virtual NoteTypeEntity NoteTypeEntity { get; set; }

public string Note { get; set; }
public string CompanyKey { get; set; }
public string ApplicationSubKey { get; set; }
public string ApplicationKey { get; set; }
}
}

And for that I created a (version 1) validation class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using FluentValidation;
using Note.Domain.Entities;

namespace Note.Domain.Validators
{
public class NoteValidator : AbstractValidator<NoteEntity>
{
public NoteValidator()
{
RuleFor(x => x.Id).NotNull();
RuleFor(x => x.Who).Length(0, 40);
RuleFor(x => x.NoteTypeId).NotNull();
RuleFor(x => x.CompanyKey).Length(1, 255);
RuleFor(x => x.ApplicationSubKey).Length(1, 255);
RuleFor(x => x.ApplicationKey).Length(1, 255);
}
}
}

Normally I annotate the entity object, but the fluent validator gives you a mechanism to move that code into it’s own class. So you can remove the validation annotations.

You need to add this validator to the startup method.

1
2
3
4
5
6
using FluentValidation;


// hook in validators before registering services
builder.Services.AddScoped<IValidator<NoteEntity>, NoteValidator>();
builder.Services.AddScoped<IValidator<NoteTypeEntity>, NoteTypeValidator>();

Typically speaking, I will generally add the validators to the repository layer. So in my NoteRepository class I would add the following code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using FluentValidation;
using FluentValidation.Results;
//
// clear object level variables
//
private readonly IValidator<NoteTypeEntity> _noteTypeValidator;
//
// in the constructor, inject your notification class
//
public NoteTypeRepository(NoteDataContext dbContext,
ILogger<NoteTypeRepository> logger,
IValidator<NoteTypeEntity> noteTypeValidator // add this
) : base(logger)
{
_dbContext = dbContext;
_noteTypeValidator = noteTypeValidator; // and this
}
//
// add a block to the top of your Create and Update methods
//
public async Task<IBaseResult> CreateNoteType(NoteTypeEntity noteType)
{
try
{
// Validate the noteType entity
ValidationResult validationResult = _noteTypeValidator.Validate(noteType);

if (!validationResult.IsValid)
{
// Handle validation failures
string errorMessages = string.Join("; ", validationResult.Errors.Select(e => e.ErrorMessage));
return new Result().ReturnFail(LogError("Validation failed: " + errorMessages));
}

_dbContext.Add(noteType);
// the code of the method(s) continues here