Menu

Validation on server side using Fluent Validation

Validation is a necessary part of every application, we will have to validate the user inputs on client side as much as possible and then on server. When it comes to ASP.NET, it much easier to do the validation using FluentValidation.

Lets think about the POST, you will need to validate the null or empty strings – easy, I know. Below is your post model.

public class QuestionViewModel : IValidatableObject
{
    public string Caption { get; set; }
    ....   
  
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var validator = new QuestionViewModelValidator();
        var result = validator.Validate(this);
        return result.Errors.Select(item => new ValidationResult(item.ErrorMessage, new[] { item.PropertyName }));
    }
}

This is your validation object.

public class QuestionViewModelValidator : AbstractValidator<QuestionViewModel>
{
    public QuestionViewModelValidator()
    {
        RuleFor(o => o.Caption).NotEmpty().WithMessage("Caption cannot be empty");
    }
}

Now in your controller.

[HttpPost]
public IActionResult Create([FromBody]QuestionViewModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var entity = Mapper.Map<Question>(model);
    _repository.Add(entity);

    var output = Mapper.Map<QuestionDetailsViewModel>(entity);

    return CreatedAtRoute("GetQuestion", new { controller = "Questions", id = output.QuestionId }, output);
}

See how you check for the ModelState.IsValid, you must be thinking that do we need a another NuGet for this ? well this is the easy stuff. refer to documentation for more advance stuff, like below.

using FluentValidation;

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);

bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;

 

Leave a comment