Simon H's answer does the job if you only want the index in the error message.
I'm not recommending anyone do this, but you can always let FluentValidation validate everything else for you and then add custom errors yourself in an override of the Validate method. You can use anything you want from the validation context and have complete control over any error that is generated
using FluentValidation;
using FluentValidation.Results;
public class NeedsValidating
{
public List<string> StringCollection { get; set; } = new List<string>();
public int OtherNumber { get; set; }
public List<string> OtherStringCollection { get; set; } = new List<string>();
}
public class IndexValidator : AbstractValidator<NeedsValidating>
{
/// <remarks>
/// The usual Fluent Validation good stuff goes in the constructor
/// </remarks>
public IndexValidator()
{
RuleFor(nv => nv.OtherStringCollection).NotEmpty().WithMessage("Whatever");
}
/// <remarks>
/// Depending on your use case, you may have to remove errors as well
/// </remarks>
public override ValidationResult Validate(ValidationContext<NeedsValidating> context)
{
var strings = context.InstanceToValidate.StringCollection;
var result = base.Validate(context);
for (int index = 0; index < strings.Count(); index++)
{
if (!IsValid(strings, index))
{
result.Errors.Add(new ValidationFailure("Custom Property with index", "Custom Message with index", strings[index]));
}
}
// keep going, validate other stuff here if you want to
return result;
}
private bool IsValid(List<string> strings, int index) => false; // throw new NotImplementedException("Whatever you want");
}
Obviously this means that with full control, you're having to write boilerplate code that the validation library normally does for you and is designed to avoid. It doesn't really make sense to write validation like this and use FluentValidation, unless you just want to really customise a couple of things
Example usage:
using Xunit;
using FluentAssertions;
[Fact]
public void TestTheValidator()
{
var input = new NeedsValidating
{
StringCollection = new List<string>{ "Whatever 1", "Whatever 2", "Whatever 3" }
};
var result = new IndexValidator().Validate(input);
result.IsValid.Should().BeFalse();
result.Errors.Should().HaveCount(4);
result.Errors.Where(e => e.ErrorMessage == "Whatever").Should().HaveCount(1);
result.Errors.Where(e => e.ErrorMessage == "Custom Message with index").Should().HaveCount(3);
}
Nameof theIOnlineCashierProductin the log message?