考虑以下简化代码:
public class Request
{
public List<Selection> Selections { get; set; }
}
public class Selection
{
public decimal Price { get; set; }
}
public class RequestValidator(): AbstractValidator<Request>
{
public RequestValidator()
{
RuleForEach(x => x.Selections).SetValidator(new SelectionValidator());
}
}
public class SelectionValidator : AbstractValidator<Selection>
{
public SelectionValidator()
{
RuleFor(x => x.Price).NotEqual(0);
}
}
如果我有一个Selection
等于0的Price
项目,我会收到错误消息:
'Price' must not be equal to '0'.
我所缺少的是引用集合中哪个元素有此错误。
在调试时,我可以清楚地看到Error.PropertyName
设置为Selections[0].Price
,但是缺少对该项目的引用的格式化名称。
是否可以正确格式化完整的属性名称?也许使用.WithMessage()
,但似乎不起作用。
为了清楚起见,我的目标是使嵌套项目的错误如下所示:
<CollectionPropertyName>[<index>].<PropertyName> <error text>
。例如Selectons[0].Price must not be equal to 0
答案 0 :(得分:1)
You can override the Validate
+ ValidateAsync
method to modify the result:
public abstract class ValidatorWithFullIndexerPath<T> : AbstractValidator<T>
{
public override ValidationResult Validate(ValidationContext<T> context)
{
var result = base.Validate(context);
FixIndexedPropertyErrorMessage(result);
return result;
}
public override async Task<ValidationResult> ValidateAsync(ValidationContext<T> context, CancellationToken cancellation = default(CancellationToken))
{
var result = await base.ValidateAsync(context, cancellation);
FixIndexedPropertyErrorMessage(result);
return result;
}
protected void FixIndexedPropertyErrorMessage(ValidationResult result)
{
if (result.Errors?.Any() ?? false)
{
foreach (var error in result.Errors)
{
// check if
if (Regex.IsMatch(error.PropertyName, @"\[\d+\]") &&
error.FormattedMessagePlaceholderValues.TryGetValue("PropertyName", out var propertyName))
{
// replace PropertyName with its full path
error.ErrorMessage = error.ErrorMessage
.Replace($"'{propertyName}'", $"'{error.PropertyName}'");
}
}
}
}
}
And, update RequestValidator
and any other classes where full path is desired:
public class RequestValidator : ValidatorWithFullIndexerPath<Request>
答案 1 :(得分:0)
FluentValidation 8.1包含一个支持此功能的新方法OverrideIndexer()
: