В моем проекте API у меня есть несколько конечных точек для простых операций CRUD.Конечные точки используют FluentValidation для проверки предоставленных моделей путем добавления валидаторов в DI и использования ModelState.IsValid
.
ModelState.IsValid отлично работает, когда в качестве параметра используется только одна модель, но как только у меня будет несколько моделейзатем проверяется только первое получение, следующий пример делает эту проблему более ясной:
Моя UPDATE
операция конечной точки принимает 2 параметра (идентификатор и модель):
public async Task<IActionResult> UpdateMedium([CustomizeValidator(RuleSet = ValidationClass.UPDATE)] [FromRoute] long id, [FromBody] Medium model)
{
if (!this.ModelState.IsValid)
{
return this.BadRequest(this.ModelState);
}
if (id != model.MediumID)
{
return this.BadRequest();
}
// Etc....
}
this.ModelState.IsValid
теперь проверяется только первая модель (Id), а вторая модель get игнорируется.Каков наилучший подход для проверки обеих моделей?
Параметр Id, очевидно, довольно прост, но я все равно сделал для него валидатор FluentValidation (на случай, если в будущем мы захотим добавить к нему больше проверочной логики):
public class IdValidator : AbstractValidator<long>
{
public IdValidator()
{
RuleFor(r => r).NotEmpty().WithMessage("Id is empty.");
}
}
Дополнительно,Средство проверки модели Medium выглядит следующим образом:
public class MediumValidator : AbstractValidator<Medium>
{
public MediumValidator()
{
RuleSet(ValidationClass.CREATE, Create);
RuleSet(ValidationClass.UPDATE, Update);
}
private void Create()
{
RuleFor(r => r.InsertDateTime).Empty().WithMessage("{PropertyName} is not empty.");
RuleFor(r => r.InsertUserID).Empty().WithMessage("{PropertyName} is not empty.");
RuleFor(r => r.SolutionID).Empty().WithMessage("{PropertyName} is not empty.");
RuleFor(r => r.Name).NotEmpty().WithMessage("{PropertyName} is not filled in.");
RuleFor(r => r.Name).MaximumLength(100).WithMessage("The length of {PropertyName} must be {MaxLength} characters or fewer. You entered {TotalLength} characters.");
}
private void Update()
{
RuleFor(r => r.UpdateDateTime).Empty().WithMessage("{PropertyName} is not empty.");
RuleFor(r => r.UpdateUserID).Empty().WithMessage("{PropertyName} is not empty.");
RuleFor(r => r.MediumID).NotEmpty().WithMessage("{PropertyName} is empty.");
RuleFor(r => r.Name).NotEmpty().WithMessage("{PropertyName} is not filled in.");
RuleFor(r => r.Name).MaximumLength(100).WithMessage("The length of {PropertyName} must be {MaxLength} characters or fewer. You entered {TotalLength} characters.");
}
}
Возможно, мне следует использовать модель только в качестве параметра, а затем просто сделать поле идентификатора обязательным?
ОБНОВЛЕНИЕ
Настройка FluentValidation при запуске:
services.AddMvc()
.AddFluentValidation(fv =>
{
fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
});
// Add fluent validators
services.AddTransient<IValidator<long>, IdValidator>();
services.AddTransient<IValidator<Medium>, MediumValidator>();
ОБНОВЛЕНИЕ2:
Я использую сваггер для проверки конечной точки (ввод JSON).