checking if parameter is one of 3 values with fluent validation
Usage:
RuleFor(m => m.Job)
.In("Carpenter", "Welder", "Developer");
Output:
Job must be one of these values: Carpenter, Welder or Developer
Extension method:
public static class ValidatorExtensions
{
public static IRuleBuilderOptions<T, TProperty> In<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, params TProperty[] validOptions)
{
string formatted;
if (validOptions == null || validOptions.Length == 0)
{
throw new ArgumentException("At least one valid option is expected", nameof(validOptions));
}
else if (validOptions.Length == 1)
{
formatted = validOptions[0].ToString();
}
else
{
// format like: option1, option2 or option3
formatted = $"{string.Join(", ", validOptions.Select(vo => vo.ToString()).ToArray(), 0, validOptions.Length - 1)} or {validOptions.Last()}";
}
return ruleBuilder
.Must(validOptions.Contains)
.WithMessage($"{{PropertyName}} must be one of these values: {formatted}");
}
}
You may do this with a list containing your conditions
var conditions = new List<string>() { str1, str2, str3 };
RuleFor(x => x.Parameter)
.Must(x => conditions.Contains(x))
.WithMessage("Please only use: " + String.Join(",", conditions));
RuleFor(x => x.Type).Must(x => x.Equals("K") || x.Equals("D")).WithMessage("Err Message!");
Agree with the code snippet from Thomas above. Another approach I like to take sometimes: if the validation makes sense as a domain concept, you can break it out into a method, such as the following:
RuleFor(x=>x.Parameter).Must(BeAValidParameter).WithMessage("Your parameter must be a valid parameter.");
private static bool BeAValidParameter(string arg)
{
return arg.Equals("str1") || arg.Equals("str2") || arg.Equals("str3");
}
I use this often for things like BeAValidZipCode
, or BeAValidPhoneNumber
, or some complex logic that expresses one business concept. You can use it in conjunction with the standard validation concepts (so, avoid trying to place all your validation in one method, for example).