FluentValidation:更新验证器中某些可选属性的已验证模型



我想知道是否可以在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,并将警告保存在变量中,但仍将模型视为有效。

更新传递给验证的对象不是一个好主意,验证器应该只验证输入实体,并返回验证结果,仅此而已。我建议你有两个验证器。一个用于业务关键规则,一个用于警告,因此,如果第一个验证器返回该模型无效,则返回结果,如果没有严重错误,则验证警告,然后您可以决定是否继续并操作您的模型! 例如

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    
}
}

实际上,操作传入的值不仅仅是验证。 所以FluentValidator可能不是最好的地方。 如何将该特定逻辑放入二传器中?

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必须是公开的,以便您使用FluentValidation访问它(我能够确认这一点(。 如果你不喜欢这样,也许你可以有一个方法访问它。 此外,它可能只是一个布尔值,当您发现其值为 true 时,您可以将文本设置在其他地方。

最后,为了确认您原来的方法可能不会像您希望的那样奏效,我在 GitHub 存储库上发现了一个封闭的问题,有人询问如何做类似的事情。 以下是JeremySkinner的回应:

嗨,FluentValidation 只对预填充的对象执行验证,它不会修改/更改属性的值。从技术上讲,您可以使用完成这项工作的自定义验证器来执行此操作,但我并不真正推荐它。

我已经设法解决了它:

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

最新更新