我为这个模型做了一个流畅的验证类
public class OnlineCashierRequest
{
Guid InvoiceId { get; set; }
string ClientPhoneOrEmail { get; set; }
List<IOnlineCashierProduct> Products { get; set; }
}
public interface IOnlineCashierProduct
{
string Name { get; set; }
decimal Amount { get; set; }
int Count { get; set; }
}
我对
products
有一个规则,其中金额等于空。但是我如何在消息行索引中写入$"Amount is less zero for row {rowIndex}"
RuleForEach(t => t.Products)
.Must(x => x.Amount < 0)
.WithMessage(x => $"[{rowIndex}] Amount must be greater then zero\r\n");
https://docs.fluidation.net/en/latest/collections.html
RuleForEach(t => t.Products)
.Must(x => x.Amount < 0)
.WithMessage(x => $"[{CollectionIndex}] Amount must be greater than zero\r\n");
如果您只需要错误消息中的索引,Simon H 的答案就可以完成任务。
我不建议任何人这样做,但您始终可以让 FluentValidation 为您验证其他所有内容,然后在覆盖
Validate
方法中自行添加自定义错误。您可以使用验证上下文中所需的任何内容,并完全控制生成的任何错误
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");
}
显然,这意味着在完全控制的情况下,您必须编写验证库通常为您执行的样板代码,并且旨在避免这种情况。像这样编写验证并使用 FluentValidation 并没有什么意义,除非您只想真正自定义一些东西
使用示例:
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);
}