Aspnetcore: IValidatableObject.Validate вызывается только в том случае, если правила проверки, определенные атрибутом, проходят?

Созданный на 11 янв. 2017  ·  3Комментарии  ·  Источник: dotnet/aspnetcore

Привет,

У меня есть объект со свойством [Required] -decorated, который реализует IValidatableObject . Во время привязки модели, если обязательное свойство имеет значение null, метод Validate() объекта никогда не вызывается. Validate() только в том случае, если проверка с настройкой атрибута проходит?

В моем случае, если пользователь отправляет форму с ошибками проверки, он сначала видит сообщение об отсутствующем поле. Затем, как только эта ошибка будет устранена и форма будет повторно отправлена, им будет представлен дополнительный список ошибок, на этот раз созданный Validate() . Есть ли способ инициировать одновременное выполнение всех проверок, чтобы пользователю был представлен список _все_ ошибок, требующих его внимания, при первой отправке формы?

Спасибо,
Бен

Версии: ASP.Net Core 1.1.0 / .Net 4.6.1

Пример кода

public class Import : IValidatableObject
{
  [Required]
  public IFormFile File { get; set; }

  public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { /* ... */ }
  //...
}

_ С контроллера: _

[HttpPost, ActionName("Index")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> IndexPost()
{
  var model = new ViewModels.Import();

  var bindingResult = await TryUpdateModelAsync(model, "", i => i.StartDate, i => i.EndDate, i => i.ImportTypeId, i => i.File);
  if (!bindingResult || ModelState.ValidationState != ModelValidationState.Valid) {
    return View(model);
  }

  // ...
}

Если пользователю не удается заполнить обязательное поле, он увидит сообщение об ошибке, но не увидит других сообщений об ошибках, которые может добавить Validate ().

Все 3 Комментарий

Этот вопрос закрывается, потому что он не обновлялся в течение 3 месяцев.

Приносим извинения, если это доставляет неудобства. Если вы по-прежнему сталкиваетесь с этой проблемой, мы просим вас регистрировать новую проблему с обновленной информацией, и мы рассмотрим ее.

Я испытываю такое же поведение в Asp.Net Core 2.0 со ссылочной библиотекой, содержащей IValidatableObject targeting .Net Standard 2.0.
Только когда будут выполнены все проверки [Required] , пользовательские проверки в Validate() будут выполнены. Другими словами, я должен отправить объект своему контроллеру со всеми необходимыми полями, прежде чем что-либо еще будет сообщено в modelstate.
Кажется, что modelstate сначала заботится о том, что требуется, а затем обо всем остальном. Я не пробовал другие стандартные атрибуты проверки, такие как [StringLength()] .

Это действительно досадный баг. Зачем закрывать?

Трудно спроектировать вещи и сказать людям, что аннотации данных работают, тогда вы обнаружите, что IValidatableObject.Validate работает, как указано выше. Это проблема, и ее СЛЕДУЕТ открыть снова.

Между тем мне приходится иметь дело с программистами, которые считают, что это хорошее программирование:
публичный статический списокValidateUpdateDates (команда ICommand)
{
var newErrors = новый список();

        var validator = new DataAnnotationsValidator();
        var results = new List<ValidationResult>();
        var isValid = validator.TryValidate(command, out results);

        if (!(command is UpdatePromotionCommand cpc))
            return newErrors;

        newErrors.AddRange(ValidateDatesAreValidFormat(cpc));

        if (
          !string.IsNullOrEmpty(cpc.PurchasePeriodStart)
          && !string.IsNullOrEmpty(cpc.PurchasePeriodEnd)
          && DateTime.TryParse(cpc.PurchasePeriodStart, out DateTime purchasePeriodStartDate)
          && DateTime.TryParse(cpc.PurchasePeriodEnd, out DateTime purchasePeriodEndDate)
          && purchasePeriodStartDate > purchasePeriodEndDate
        )
        {
            newErrors.Add(new ECError("Purchase Period End cannot be before Purchase Period Start."));
        }

        if (
          !string.IsNullOrEmpty(cpc.ClaimPeriodStart)
          && !string.IsNullOrEmpty(cpc.ClaimPeriodEnd)
          && DateTime.TryParse(cpc.ClaimPeriodStart, out DateTime claimPeriodStartDate)
          && DateTime.TryParse(cpc.ClaimPeriodEnd, out DateTime claimPeriodEndDate)
          && claimPeriodStartDate > claimPeriodEndDate
        )
        {
            newErrors.Add(new ECError("Claim Period End cannot be before Claim Period Start."));
        }
Была ли эта страница полезной?
0 / 5 - 0 рейтинги