0

モデル エンティティにIValidatableObjectを実装し、 Validate(ValidationContext)を使用して、多くの場合複雑な検証を実行しています。

ValidationContextを使用して、さまざまな検証シーンを区別できますか?

たとえば、3 つの検証シーンがある User モデルを例にとります。

  • サインアップ – 電子メールが一意であるか、少数の必須フィールドが入力されているかをテストしたい
  • 詳細の変更 – 電子メールの一意性チェックが異なります。サインアップ後に必要な詳細が少し増えます。ここではパスワードを変更しないため、チェックする必要はありません。
  • パスワードの変更 – 検証するパスワード フィールドのみ

これは適切な使用法ですか?もしそうなら、ポストの後、Validate() が呼び出される前に、正しい ValidationContext プロパティが設定されていることを確認するにはどうすればよいですか? それとも、まったく別のアプローチをとるべきですか?

4

2 に答える 2

1

私の 2 セントの価値については、モデルが有効な状態 (すべての検証基準を適用) であるか、そうでないかのいずれかです。特定の状況下で検証を適用したくない場合は、実際には別のモデル (実際には ViewModel) を使用する必要があると思います。

あなたの例ではRegisterViewModel、サインアップ用とEditUserViewModel 詳細の変更用に別々に作成します。これらにはそれぞれ独自の検証があり、単一の責任があります。

多くの異なるビューで再利用するファット モデルを作成することは、ちょっとしたコードの匂いがします。私がそう考えるにはいくつかの理由があります。まず、ユーザー データとのすべてのやり取りに使用される単一のモデルがあるとします。次のようになります。

public class UserModel
{
    public int UserId { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public bool IsAdministrator { get; set; }
}

後で、サイトへの登録時に使用されたブラウザーを追跡することにしました。それをどこに追加しますか?それは実際にはユーザーとは何の関係もないので、UserModelモデルに入るべきではありません。別のものを持っている場合はRegisterViewModel、登録プロセスが変更されたときに、それが使用されている他の場所にどのように影響するかを気にせずに、必要に応じて変更できます.

たとえば、MVC の DefaultModelBinder で上記のモデルを使用していた場合、より深刻な問題が発生します。hereで説明されているように、フォームにフィールドがない場合でも、ユーザーは独自のリクエストを作成し、自分自身に管理者権限を付与することができますIsAdministrator(一括割り当ての脆弱性を悪用することにより)。この場合も、プロパティを指定せずに別の ViewModel を使用するIsAdministratorと、セキュリティ ホールの領域が減少します。

上記は一例ですが、ご理解いただければ幸いです。

于 2012-06-23T15:00:22.723 に答える
1

IValidatableObject、単一のモデルに対して複数の検証を実行するために使用されます。あなたの場合、Userモデルがあり、3 つの検証を実行したい場合、モデルに を実装することで完全に実行できIValidatableObjectますUser

メソッドですべてのValidationContextプロパティに直接アクセスできるため、(コンテキストへのアクセスを提供する以外に) あまりメリットはありませんValidate

によって単一のモデルに関連する複数の検証を実行する例IValidatableObject。(それで、ValidationContextここの用途は何ですか?)

public class Party : IValidatableObject
{
    [Required(ErrorMessage = "Start date is required")]
    [FutureDateValidator(ErrorMessage = "Start date should be a future date")]
    public DateTime StartDate { get; set; }

    [Required(ErrorMessage = "Duration is required")]    
    public int DurationInHours { get; set; }

    [Required(ErrorMessage = "No. of joinees is required")]
    [Range(2, 10, ErrorMessage = "No. of joinees should be minimum 2 and not more than 10")]
    public int NoOfJoinees { get; set; }    

    public bool Drinks { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (StartDate.TimeOfDay > new TimeSpan(22 - DurationInHours, 0, 0))
        {
            yield return new ValidationResult("The party should not exceed after 10.00 PM");
        }

        if (NoOfJoinees < 5 && Drinks)
        {
            yield return new ValidationResult("Drinks are only allowed if no. of joinees is 5 or more.");
        }
    }
}
于 2012-06-23T16:09:44.877 に答える