11

I am looking to validate both my Dto's and Domain models using FluentValidation. I already defined a Validator class to validate my Dto as seen below.

However if I want to add a Validator for my Domain model as well, a change in one of the Validator's will not reflect in the other. As in, if I change the rule for Password length from 6 to 7, I will have to change it on both places.

Is there some way of potentially inheriting the rules from the domain model or something similar, to achieve consistent rules across Dto's and Domain models?

Dto:

public class NewUserDto
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

public class NewUserDtoValidator : AbstractValidator<NewUserDto>
{
    public NewUserDtoValidator()
    {
        RuleFor(x => x.FirstName).Length(2, 50);
        RuleFor(x => x.LastName).Length(2, 50);
        RuleFor(x => x.Email).EmailAddress();
        RuleFor(x => x.Username).Length(4, 25);
        RuleFor(x => x.Password).MinimumLength(6);
    }
}

Domain Model:

public class User
{
    public uint Id { get; private set; }

    public string Username { get; private set; }
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public string Email { get; private set; }
    public DateTime RegistrationDate { get; private set; }
    public string Hash { get; private set; }
    public string Salt { get; private set; }
}
bbartels
  • 355
  • 3
  • 9
  • 2
    If you had to choose, validation of the domain models is most important because that's where real logic is. If you're always working with valid domain models then DTOs returned from the domain will be valid, and invalid DTOs coming into the domain will be rejected if they can't be used to form valid domain models. – Scott Hannen Feb 03 '18 at 19:22
  • 2
    @ScottHannen But I would like to return why the DTO posted from the client is invalid and I don't really want to return Business Layer error messages to the client. I feel like this is a problem that should be more common. Not really sure why there is no easy way of doing this. – bbartels Feb 03 '18 at 22:10
  • I'm not saying don't validate the dto. But it sounded like you were validating the dto instead of the domain model, or on the fence about where to validate. – Scott Hannen Feb 03 '18 at 22:26
  • @ScottHannen I am looking to validate both. What I was looking for was a way of sharing the logic between the validation of the Dto and the Domain model. So I when changes happen to the rules, I don't have to update each Dto relating to that domain model. – bbartels Feb 03 '18 at 22:28
  • 1
    If it doesn't contradict with your design you can create an interface for common fields and a base validator: `class BaseUserValidator: AbstractValidator {}` – Roman Koliada Feb 06 '18 at 11:39
  • 1
    @bbartels It's problems like this that keep me awake at 2 AM. What approach did you end up going with for this? Currently the project I'm working with is simple enough that I don't bother with DTO's - I deserialize straight to the domain entities and apply the validation rules for them via FluentValidation. However, it might be time for me to create DTO's, but with that comes the concern about duplicating not only data but also validation logic. – Tagc Jun 29 '20 at 00:39

1 Answers1

-2

For sharing same validation rules between entities, you can use custom validators: https://github.com/JeremySkinner/FluentValidation/wiki/e.-Custom-Validators

Vladislav Rastrusny
  • 29,378
  • 23
  • 95
  • 156