One Message for rule chain?
The most straightforward solution would be to just set the message to a variable, and apply the same message after each rule:
var message = "Minimum Age entry is required and must range from 1 to 99 years.";
RuleFor(s => s.ProposalDetail.AgeMin)
.NotNull()
.WithMessage(message)
.GreaterThanOrEqualTo(1)
.WithMessage(message)
.LessThanOrEqualTo(99)
.WithMessage(message);
Update 4
I found a simpler solution that works with any version using the Configure
method, so my original "Extension method" approach is not needed anymore
using FluentValidation;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(s => s.Id).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.Configure(rule => rule.MessageBuilder = _ => "Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
}
Original answer: It works up to version 9 but it's more complex than the above
you can accomplish what you want with a simple extension method
using FluentValidation;
using FluentValidation.Internal;
using FluentValidation.Resources;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(s => s.Id).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.WithGlobalMessage("Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
public static class MyExtentions
{
public static IRuleBuilderOptions<T, TProperty> WithGlobalMessage<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, string errorMessage)
{
foreach (var item in (rule as RuleBuilder<T, TProperty>).Rule.Validators)
item.Options.ErrorMessageSource=new StaticStringSource(errorMessage);
return rule;
}
}
}
The below works for any version but since it uses the Must
method , it's not very clean and you miss the feel of a fluent interface.
using FluentValidation;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(x => x)
.Must(x => x.Id != null && x.Id >= 1 && x.Id <= 99)
.WithMessage("Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
}
Update 3: (Apr 04/07/2019)
In FluentValidation v8.2.2, The IRuleBuilderOptions
interface do not have direct access to IRuleBuilderOptions.ErrorMessageSource
property anymore, instead we should use: IRuleBuilderOptions.Options.ErrorMessageSource
.