我将我的 web api 从 asp net core 3.1 迁移到 .net 6,我在使用 FluentValidation 库时遇到了一些问题。
RuleFor(x => x.Name)
.NotEmpty()
.OnFailure(x =>
{
var message = "El nombre del Usuario es requerido.";
throw new HttpException(message, message, (int)HttpStatusCode.BadRequest);
})
.Length(1, 150)
.OnFailure(x =>
{
var message = "El nombre del Usuario debe contener hasta máximo 150 caracteres.";
throw new HttpException(message, message, (int)HttpStatusCode.BadRequest);
});
此代码过去可以正常工作,但是,当我更新库时,不推荐使用 .OnFailure() 方法。
我想知道如何像以前那样为每个 OnFailure 抛出自定义异常,其中 HttpException 是继承自 Exception 的自定义类。 json 结果的一个例子是:
{
"developerMessage": "El nombre del Usuario es requerido..",
"userMessage": "El nombre del Usuario es requerido.",
"errorCode": 400,
"moreInfo": ""
}
更新!
我关注了这篇文章https://www.tutorialspoint.com/what-is-use-of-fluent-validation-in-chash-and-how-to-use-in-chash。我使用 CascadeMode.Stop 因为前一个已弃用,但是当我尝试测试 .Lenght 验证时,结果变量显示每个 RuleFor() 的第一个错误。我的意思是:如果我有 3 个 RuleFor() 并且每个规则有 2 个验证器,结果变量显示每个 RuleFor() 的第一个错误消息的验证器并且没有真正失败的错误消息。
我该如何解决这个问题?
public UserValidator()
{
RuleFor(x => x.Name)
.Cascade(CascadeMode.Stop)
.NotEmpty().WithMessage("El nombre del Usuario es requerido.")
.Length(1, 150).WithMessage("El nombre del Usuario debe contener hasta máximo 150 caracteres.");
var result = Validate(new User()); //I need to get the context (user) to validate it , **not new User()**
if(!result.IsValid)
{
foreach(var error in result.Errors)
{
var message = $"{error.ErrorMessage}";
throw new HttpException(message, message, (int)HttpStatusCode.BadRequest);
}
}
}
您可以使用继承自
ValidateAndThrow
类的验证类的AbstractValidator<T>
方法
在你的情况下,因为你想抛出
HttpException
异常,你必须覆盖验证类的 RaiseValidationException
方法,以便它们可以抛出所需的异常。
有两种方法可以做到这一点:
1 - 为每个验证类重写
RaiseValidationException
方法:
public class UserValidator : AbstractValidator<User>
{
public UserValidator()
{
RuleFor(x => x.Name)
.Cascade(CascadeMode.Stop)
.NotEmpty()
.WithMessage("El nombre del Usuario es requerido.")
.Length(1, 150)
.WithMessage("El nombre del Usuario debe contener hasta máximo 150 caracteres.");
}
// Add this override on your validation class
protected override void RaiseValidationException(ValidationContext<IntegrateAccountingOfficeWithAsaasCommand> context, ValidationResult result)
{
var firstError = result.Errors[0];
var ex = new HttpExcpetion(firstError.ErrorMessage, (int)HttpStatusCode.BadRequest);
throw ex;
}
}
2 - 创建一个方法覆盖的抽象类,这样就不需要重新实现每个验证类:
public abstract class CustomAbstractValidator<T> : AbstractValidator<T>
{
protected override void RaiseValidationException(ValidationContext<IntegrateAccountingOfficeWithAsaasCommand> context, ValidationResult result)
{
var firstError = result.Errors[0];
var ex = new HttpExcpetion(firstError.ErrorMessage, (int)HttpStatusCode.BadRequest);
throw ex;
}
}
public class UserValidator : CustomAbstractValidator<User>
{
public UserValidator()
{
RuleFor(x => x.Name)
.Cascade(CascadeMode.Stop)
.NotEmpty()
.WithMessage("El nombre del Usuario es requerido.")
.Length(1, 150)
.WithMessage("El nombre del Usuario debe contener hasta máximo 150 caracteres.");
}
}
实现后,只需获取您的验证器实例并调用
ValidateAndThrow
方法:
1 - 没有依赖注入:
public class YourProgramFlowClass
{
public void YourMethod()
{
// ... before validation code
var validator = new UserValidator();
validator.ValidateAndThrow(user);
// ... after validation code
}
}
2 - 没有依赖注入:
public class YourProgramFlowClass
{
private readonly IValidator<ClassToValidate> _validator;
public YourProgramFlowClass(IValidator<ClassToValidate> validator)
{
_validator = validator;
}
public void YourMethod()
{
// ... before validation code
_validator.ValidateAndThrow(user);
// ... after validation code
}
}