Aspnetcore: IValidatableObject.Validateは、属性定義の検証ルールに合格した場合にのみ呼び出されますか?

作成日 2017年01月11日  ·  3コメント  ·  ソース: dotnet/aspnetcore

こんにちは、

IValidatableObjectを実装する[Required]装飾されたプロパティを持つオブジェクトがあります。 モデルのバインド中に、必要なプロパティが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でもこの動作が発生しており、.Net Standard2.0を対象とするIValidatableObjectを含む参照ライブラリがあります。
Validate()のカスタム検証が実行されるのは、すべての[Required]検証が満たされるまでです。 つまり、modelstateで他の何かが報告される前に、すべての必須フィールドを含むオブジェクトをコントローラーに投稿する必要があります。
modelstateは、最初に必要なものを気にし、次に他のすべてを気にするようです。 [StringLength()]ような他の標準検証属性は試していません。

これは本当に厄介なバグです。 なぜそれを閉じるのですか?

物事を設計して人々にデータ注釈が機能することを伝えるのは難しいので、IValidatableObject.Validateは上記のように実行されます。 これは問題であり、これを再開する必要があります。

その間、私はこれが良いプログラミングだと思うプログラマーに対処しなければなりません:
パブリック静的リストValidateUpdateDates(ICommandコマンド)
{{
var newErrors = new List();

        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 評価