规则链的一条消息?
One Message for rule chain?
我在使用 FluentValidation 时遇到问题,无论给定链中的验证错误如何,我都想显示一条消息。例如,我在下面为 属性 定义了一个验证链。我希望对链进行评估,任何失败都会导致下面的 WithMessage()
调用中定义的消息。但是,它似乎短路了,只显示遇到的第一个错误的 FluentValidation 默认错误消息。请参阅下面的代码:
RuleFor(s => s.ProposalDetail.AgeMin).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.WithMessage("Minimum Age entry is required and must range from 1 to 99 years.");
实际情况是 AgeMin 属性 为空,因此第一个 NotNull()
检查失败,验证消息为“'Proposal Detail. Age Min' 不得为空”。 Proposal Detail 是封装视图模型的名称。
我已经尝试将整个验证器的 CascadeMode 设置为 CascadeMode.Continue,但没有效果。
我怎样才能完成一条消息一条 属性 验证链?
更新 4
我找到了一个更简单的解决方案,它适用于使用 Configure
方法的任何版本,因此不再需要我原来的“扩展方法”方法
using FluentValidation;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(s => s.Id).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.Configure(rule => rule.MessageBuilder = _ => "Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
}
原回答:版本9之前都可以,但是比上面的复杂
你可以用一个简单的扩展方法来完成你想要的
using FluentValidation;
using FluentValidation.Internal;
using FluentValidation.Resources;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(s => s.Id).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.WithGlobalMessage("Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
public static class MyExtentions
{
public static IRuleBuilderOptions<T, TProperty> WithGlobalMessage<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, string errorMessage)
{
foreach (var item in (rule as RuleBuilder<T, TProperty>).Rule.Validators)
item.Options.ErrorMessageSource=new StaticStringSource(errorMessage);
return rule;
}
}
}
以下适用于任何版本,但由于它使用 Must
方法,它不是很干净,您会怀念流畅界面的感觉。
using FluentValidation;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(x => x)
.Must(x => x.Id != null && x.Id >= 1 && x.Id <= 99)
.WithMessage("Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
}
更新 3:(2019 年 4 月 7 日)
在 FluentValidation v8.2.2 中,IRuleBuilderOptions
接口不再直接访问 IRuleBuilderOptions.ErrorMessageSource
属性,我们应该使用:IRuleBuilderOptions.Options.ErrorMessageSource
.
最直接的解决方案是将消息设置为变量,并在每个规则后应用相同的消息:
var message = "Minimum Age entry is required and must range from 1 to 99 years.";
RuleFor(s => s.ProposalDetail.AgeMin)
.NotNull()
.WithMessage(message)
.GreaterThanOrEqualTo(1)
.WithMessage(message)
.LessThanOrEqualTo(99)
.WithMessage(message);
替换 ErrorMessageSource
的过时 属性 赋值,并使用波纹管替代 FluentValidation 版本 >= 9.x
public static class ValidatorExtensions
{
public static IRuleBuilderOptions<T, TProperty> WithGlobalMessage<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, string errorMessage)
{
var rules = rule as RuleBuilder<T, TProperty>;
foreach (var item in rules.Rule.Validators)
{
item.Options.SetErrorMessage(errorMessage);
}
return rule;
}
}
我在使用 FluentValidation 时遇到问题,无论给定链中的验证错误如何,我都想显示一条消息。例如,我在下面为 属性 定义了一个验证链。我希望对链进行评估,任何失败都会导致下面的 WithMessage()
调用中定义的消息。但是,它似乎短路了,只显示遇到的第一个错误的 FluentValidation 默认错误消息。请参阅下面的代码:
RuleFor(s => s.ProposalDetail.AgeMin).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.WithMessage("Minimum Age entry is required and must range from 1 to 99 years.");
实际情况是 AgeMin 属性 为空,因此第一个 NotNull()
检查失败,验证消息为“'Proposal Detail. Age Min' 不得为空”。 Proposal Detail 是封装视图模型的名称。
我已经尝试将整个验证器的 CascadeMode 设置为 CascadeMode.Continue,但没有效果。
我怎样才能完成一条消息一条 属性 验证链?
更新 4
我找到了一个更简单的解决方案,它适用于使用 Configure
方法的任何版本,因此不再需要我原来的“扩展方法”方法
using FluentValidation;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(s => s.Id).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.Configure(rule => rule.MessageBuilder = _ => "Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
}
原回答:版本9之前都可以,但是比上面的复杂
你可以用一个简单的扩展方法来完成你想要的
using FluentValidation;
using FluentValidation.Internal;
using FluentValidation.Resources;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(s => s.Id).NotNull()
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(99)
.WithGlobalMessage("Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
public static class MyExtentions
{
public static IRuleBuilderOptions<T, TProperty> WithGlobalMessage<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, string errorMessage)
{
foreach (var item in (rule as RuleBuilder<T, TProperty>).Rule.Validators)
item.Options.ErrorMessageSource=new StaticStringSource(errorMessage);
return rule;
}
}
}
以下适用于任何版本,但由于它使用 Must
方法,它不是很干净,您会怀念流畅界面的感觉。
using FluentValidation;
using FluentValidation.Results;
using System;
using System.Linq;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer() { };
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
Console.WriteLine(results.Errors.First().ErrorMessage);
Console.ReadLine();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(x => x)
.Must(x => x.Id != null && x.Id >= 1 && x.Id <= 99)
.WithMessage("Minimum Age entry is required and must range from 1 to 99 years.");
}
}
public class Customer { public int? Id { get; set; } }
}
更新 3:(2019 年 4 月 7 日)
在 FluentValidation v8.2.2 中,IRuleBuilderOptions
接口不再直接访问 IRuleBuilderOptions.ErrorMessageSource
属性,我们应该使用:IRuleBuilderOptions.Options.ErrorMessageSource
.
最直接的解决方案是将消息设置为变量,并在每个规则后应用相同的消息:
var message = "Minimum Age entry is required and must range from 1 to 99 years.";
RuleFor(s => s.ProposalDetail.AgeMin)
.NotNull()
.WithMessage(message)
.GreaterThanOrEqualTo(1)
.WithMessage(message)
.LessThanOrEqualTo(99)
.WithMessage(message);
替换 ErrorMessageSource
的过时 属性 赋值,并使用波纹管替代 FluentValidation 版本 >= 9.x
public static class ValidatorExtensions
{
public static IRuleBuilderOptions<T, TProperty> WithGlobalMessage<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, string errorMessage)
{
var rules = rule as RuleBuilder<T, TProperty>;
foreach (var item in rules.Rule.Validators)
{
item.Options.SetErrorMessage(errorMessage);
}
return rule;
}
}