FluentValidation:更新验证器内部一些可选属性的验证模型
FluentValidation: Update the validated model for some optional properties inside the validator
我想知道是否可以在 FluentValidations 验证器中为一些可选参数更新验证模型,以防这些参数无效?
这是一些代码:
public class Customer
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.FirstName).NotNull().Length(5, 100);
RuleFor(customer => customer.LastName).NotNull().Length(5, 100);
RuleFor(customer => customer.MiddleName).Length(5, 100).When(c => string.IsNullOrWhiteSpace(c.MiddleName));
}
}
我是这样使用它的:
Customer customer = new Customer { FirstName = "first name", LastName = "last name" };
CustomerValidator validator = new CustomerValidator();
var result = validator.Validate(customer);
Console.WriteLine(result.IsValid);
所以在我的例子中,我想在中间名无效时将其设置为 null,并在变量中保存警告,但仍将模型视为有效。
实际上操作传入的值不仅仅是验证。所以 FluentValidator 可能不是它的最佳位置。如何将特定逻辑放入 setter?:
string middleName;
public string MiddleName {
get => middleName;
set {
middleName =
value.Length < 5 || value.Length > 100
? null
: value;
}
编辑:回应评论中提出的问题
因此,关于您希望显示一条警告消息。我假设您已经知道如何在 FluentValidation 中执行此操作。这似乎是一个不太有趣的话题,至少在我查找 资源时是这样。所以我会把实际的警告逻辑从这个响应中去掉。
但是,为了让您有机会发出这样的警告,您需要将其存储在某个地方。因此,只需为此添加一个字段并在您的 setter 逻辑中处理它:
public string middleNameWarning;
string middleName;
public string MiddleName {
get => middleName;
set {
if (value.Length < 5 || value.Length > 100) {
middleName = null;
middleNameWarning =
$"'{value}' is not a valid MiddleName. It was reset to null. "
+ "Set MiddleName explicitly to a valid value to remove this warning.";
}
else {
middleName = value;
middleNameWarning = null;
}
}
}
middleNameWarning
必须是 public 才能使用 FluentValidation 访问它(我能够确认这一点)。如果您不喜欢那样,也许您可以通过一种方法访问它。此外,它可能只是一个布尔值,当您发现它的值为真时,您可以在其他地方设置文本。
最后,为了确认您最初的方法可能无法像您希望的那样工作,我在 GitHub 存储库中发现了一个已关闭的 issue,供询问如何做类似事情的人使用。这是 JeremySkinner 的回复:
Hi, FluentValidation only performs validation on a pre-populated object, it doesn't modify/change the values of properties. You could technically do this with a custom validator that does the work, but I wouldn't really recommend it.
更新传递给验证的对象不是一个好主意,Validator 应该只验证输入实体,return 验证结果就是这样。我建议你有两个验证器。一个用于业务关键规则,一个用于警告,因此如果第一个验证器 returns 该模型无效,您 return 结果,如果没有严重错误,则您验证警告,然后您可以决定继续或不要和你的模型一起操纵!
例如
public class Customer
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
public class CustomerCriticalValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.FirstName).NotNull().Length(5, 100);
RuleFor(customer => customer.LastName).NotNull().Length(5, 100);
}
}
public class CustomerWarningValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.MiddleName).Length(5, 100).When(c => string.IsNullOrWhiteSpace(c.MiddleName));
}
}
然后在代码中
Customer customer = new Customer();
CustomerCriticalValidator criticalValidator = new CustomerCriticalValidator();
CustomerWarningValidator warningValidator = new CustomerWarningValidator();
var validationResult = criticalValidator.Validate(customer);
if (validationResult.IsValid)
{
var result = warningValidator.Validate(customer);
if (!result.IsValid)
{
//DO what you need with customer
}
}
我已经解决了:
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.FirstName).NotNull().Length(5, 100);
RuleFor(customer => customer.LastName).NotNull().Length(5, 100).OnAnyFailure((customer) =>
{
customer.LastName = null;
customer.Warnings.Add(nameof(customer.LastName));
});
RuleFor(customer => customer.MiddleName).Length(5, 100).When(c => string.IsNullOrWhiteSpace(c.MiddleName));
}
}
我想知道是否可以在 FluentValidations 验证器中为一些可选参数更新验证模型,以防这些参数无效?
这是一些代码:
public class Customer
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.FirstName).NotNull().Length(5, 100);
RuleFor(customer => customer.LastName).NotNull().Length(5, 100);
RuleFor(customer => customer.MiddleName).Length(5, 100).When(c => string.IsNullOrWhiteSpace(c.MiddleName));
}
}
我是这样使用它的:
Customer customer = new Customer { FirstName = "first name", LastName = "last name" };
CustomerValidator validator = new CustomerValidator();
var result = validator.Validate(customer);
Console.WriteLine(result.IsValid);
所以在我的例子中,我想在中间名无效时将其设置为 null,并在变量中保存警告,但仍将模型视为有效。
实际上操作传入的值不仅仅是验证。所以 FluentValidator 可能不是它的最佳位置。如何将特定逻辑放入 setter?:
string middleName;
public string MiddleName {
get => middleName;
set {
middleName =
value.Length < 5 || value.Length > 100
? null
: value;
}
编辑:回应评论中提出的问题
因此,关于您希望显示一条警告消息。我假设您已经知道如何在 FluentValidation 中执行此操作。这似乎是一个不太有趣的话题,至少在我查找
但是,为了让您有机会发出这样的警告,您需要将其存储在某个地方。因此,只需为此添加一个字段并在您的 setter 逻辑中处理它:
public string middleNameWarning;
string middleName;
public string MiddleName {
get => middleName;
set {
if (value.Length < 5 || value.Length > 100) {
middleName = null;
middleNameWarning =
$"'{value}' is not a valid MiddleName. It was reset to null. "
+ "Set MiddleName explicitly to a valid value to remove this warning.";
}
else {
middleName = value;
middleNameWarning = null;
}
}
}
middleNameWarning
必须是 public 才能使用 FluentValidation 访问它(我能够确认这一点)。如果您不喜欢那样,也许您可以通过一种方法访问它。此外,它可能只是一个布尔值,当您发现它的值为真时,您可以在其他地方设置文本。
最后,为了确认您最初的方法可能无法像您希望的那样工作,我在 GitHub 存储库中发现了一个已关闭的 issue,供询问如何做类似事情的人使用。这是 JeremySkinner 的回复:
Hi, FluentValidation only performs validation on a pre-populated object, it doesn't modify/change the values of properties. You could technically do this with a custom validator that does the work, but I wouldn't really recommend it.
更新传递给验证的对象不是一个好主意,Validator 应该只验证输入实体,return 验证结果就是这样。我建议你有两个验证器。一个用于业务关键规则,一个用于警告,因此如果第一个验证器 returns 该模型无效,您 return 结果,如果没有严重错误,则您验证警告,然后您可以决定继续或不要和你的模型一起操纵! 例如
public class Customer
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
public class CustomerCriticalValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.FirstName).NotNull().Length(5, 100);
RuleFor(customer => customer.LastName).NotNull().Length(5, 100);
}
}
public class CustomerWarningValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.MiddleName).Length(5, 100).When(c => string.IsNullOrWhiteSpace(c.MiddleName));
}
}
然后在代码中
Customer customer = new Customer();
CustomerCriticalValidator criticalValidator = new CustomerCriticalValidator();
CustomerWarningValidator warningValidator = new CustomerWarningValidator();
var validationResult = criticalValidator.Validate(customer);
if (validationResult.IsValid)
{
var result = warningValidator.Validate(customer);
if (!result.IsValid)
{
//DO what you need with customer
}
}
我已经解决了:
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.FirstName).NotNull().Length(5, 100);
RuleFor(customer => customer.LastName).NotNull().Length(5, 100).OnAnyFailure((customer) =>
{
customer.LastName = null;
customer.Warnings.Add(nameof(customer.LastName));
});
RuleFor(customer => customer.MiddleName).Length(5, 100).When(c => string.IsNullOrWhiteSpace(c.MiddleName));
}
}