我具有WebAPI(.NET Core),并使用FluentValidator验证模型,包括更新。 我使用PATCH动词,并具有以下方法:
public IActionResult Update(int id, [FromBody] JsonPatchDocument<TollUpdateAPI> jsonPatchDocument)
{
另外,我有一个验证器类:
public class TollUpdateFluentValidator : AbstractValidator<TollUpdateAPI>
{
public TollUpdateFluentValidator ()
{
RuleFor(d => d.Date)
.NotNull().WithMessage("Date is required");
RuleFor(d => d.DriverId)
.GreaterThan(0).WithMessage("Invalid DriverId");
RuleFor(d => d.Amount)
.NotNull().WithMessage("Amount is required");
RuleFor(d => d.Amount)
.GreaterThanOrEqualTo(0).WithMessage("Invalid Amount");
}
}
并在启动类中映射此验证器:
services.AddTransient<IValidator<TollUpdateAPI>, TollUpdateFluentValidator>();
但不起作用。如何为我的任务编写有效的FluentValidator?
答案 0 :(得分:0)
您将需要手动触发验证。 您的操作方法将如下所示:
public IActionResult Update(int id, [FromBody] JsonPatchDocument<TollUpdateAPI> jsonPatchDocument)
{
// Load your db entity
var myDbEntity = myService.LoadEntityFromDb(id);
// Copy/Map data to the entity to patch using AutoMapper for example
var entityToPatch = myMapper.Map<TollUpdateAPI>(myDbEntity);
// Apply the patch to the entity to patch
jsonPatchDocument.ApplyTo(entityToPatch);
// Trigger validation manually
var validationResult = new TollUpdateFluentValidator().Validate(entityToPatch);
if (!validationResult.IsValid)
{
// Add validation errors to ModelState
foreach (var error in validationResult.Errors)
{
ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
}
// Patch failed, return 422 result
return UnprocessableEntity(ModelState);
}
// Map the patch to the dbEntity
myMapper.Map(entityToPatch, myDbEntity);
myService.SaveChangesToDb();
// So far so good, patch done
return NoContent();
}
答案 1 :(得分:0)
您可以为此使用自定义规则构建器。它可能不是最优雅的处理方式,但至少验证逻辑是您期望的位置。
假设您具有以下请求模型:
public class CarRequestModel
{
public string Make { get; set; }
public string Model { get; set; }
public decimal EngineDisplacement { get; set; }
}
您的Validator类可以继承自AbstractValidator
的{{1}},而不是具体的请求模型类型。
另一方面,流利的验证器为我们提供了不错的扩展点,例如“自定义”规则。
结合这两个想法,您可以创建如下内容:
JsonPatchDocument
在某些情况下,写下从域的角度来看不允许但在中定义的所有动作可能很繁琐。
可以通过定义 none但是规则来缓解此问题,这些规则将从您的域的角度定义有效的一组操作。
答案 2 :(得分:0)
下面的实现允许在 IValidator<Model>
中使用 IValidator<JsonPatchDocument<Model>>
,但您需要创建具有有效属性值的模型。
public class ModelValidator : AbstractValidator<JsonPatchDocument<Model>>
{
public override ValidationResult Validate(ValidationContext<JsonPatchDocument<Model>> context)
{
return _validator.Validate(GetRequestToValidate(context));
}
public override Task<ValidationResult> ValidateAsync(ValidationContext<JsonPatchDocument<Model>> context, CancellationToken cancellation = default)
{
return _validator.ValidateAsync(GetRequestToValidate(context), cancellation);
}
private static Model GetRequestToValidate(ValidationContext<JsonPatchDocument<Model>> context)
{
var validModel = new Model()
{
Name = nameof(Model.Name),
Url = nameof(Model.Url)
};
context.InstanceToValidate.ApplyTo(validModel);
return validModel;
}
private class Validator : AbstractValidator<Model>
{
/// <inheritdoc />
public Validator()
{
RuleFor(r => r.Name).NotEmpty();
RuleFor(r => r.Url).NotEmpty();
}
}
private static readonly Validator _validator = new();
}