【问题标题】:RuleForEach - need access to item's indexRuleForEach - 需要访问项目的索引
【发布时间】:2019-03-01 19:35:34
【问题描述】:

考虑到这个简化的代码:

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 项目,其中 Price 等于 0,我会收到错误消息: 'Price' must not be equal to '0'.

我缺少的是对集合中的哪个元素有此错误的引用。

调试时我可以清楚地看到Error.PropertyName 设置为Selections[0].Price,但格式化名称缺少对该项目的引用。

有没有办法正确格式化完整的属性名称?也许通过使用.WithMessage() 但它似乎不起作用。

为了清楚起见,我的目标是在嵌套项目上出现错误,如下所示: &lt;CollectionPropertyName&gt;[&lt;index&gt;].&lt;PropertyName&gt; &lt;error text&gt;。前任。 Selectons[0].Price must not be equal to 0

【问题讨论】:

标签: c# fluentvalidation


【解决方案1】:

您可以重写Validate + ValidateAsync 方法来修改结果:

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}'");
                }
            }
        }
    }
}

并且,更新 RequestValidator 和任何其他需要完整路径的类:

public class RequestValidator : ValidatorWithFullIndexerPath<Request>

【讨论】:

  • 谢谢,我已经开始朝同一个方向努力——希望有一些可用的内置功能。
【解决方案2】:

FluentValidation 8.1 包含一个新方法 OverrideIndexer() 来支持这一点:

【讨论】:

    猜你喜欢
    • 2015-04-09
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 2023-03-27
    • 2023-03-05
    • 2018-06-15
    • 2015-08-09
    • 1970-01-01
    相关资源
    最近更新 更多