3

数値を検証するメソッドがありますが、作成が複雑なため、正規表現はありません。

public bool IsRegistrationNumberValid(int number)
{
...

}

フォームにテキスト ボックスがあり、この列の検証を追加したいと考えています。カスタム アノテーションを作成するか、ModelState オブジェクトにフックしてエラー メッセージを追加するにはどうすればよいですか?

私の POST コントローラのアクションは次のようなものです:

    [HttpPost]
    public ActionResult Create(UserRegistrationViewData model)
    {
        if (ModelState.IsValid)
        {
        ...
        }
    }

どのようなオプションがあるかわかりません。カスタム属性を作成してモデルに追加できますか? または、モデル状態にフックして、チェックする前にエラーメッセージを追加する必要がありModelState.IsValidますか?

4

1 に答える 1

10

これにはいくつかのアプローチがあり、最適なアプローチは次の要素によって異なります。

  • メソッドが配置されている場所IsRegistrationNumberValidと、ロジックを移動するかどうか。
  • ユーザー入力またはドメインの整合性を検証していますか (両方をチェックする必要がありますが、それぞれの検証は別の場所で行われます)。
  • 個人の好み。

私の見方では、次のオプションが利用可能です。

  1. コントローラーのアクション メソッドで検証します。
  2. インターフェイスを使用して検証しIValidatableObjectます。
  3. カスタムを使用しますValidationAttribute
  4. サービス層で検証します。

オプション 1: コントローラーで検証します。

まず、コントローラーのアクション メソッドの値を検証し、次のModelStateように更新するだけです。

[HttpPost]
public ActionResult Create(UserRegistrationViewData model)
{
    if (ModelState.IsValid)
    {
        if (!someObject.IsRegistrationNumberValid(model.value))
        {
            ModelState.AddModelError("PropertyName", "There is an error..");
            Return View()
        }
        else
        {
            // Carry out successful action here...
        }
    }
}

オプション 2:IValidatableObjectインターフェイスを使用します。

2 番目のよりクリーンな方法はIValidatableObject、コントローラーからロジックを移動できるように、viewModel にインターフェイスを実装することです。

public class ViewModel : IValidatableObject
{
    public int Value { get; set; }

    IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
    {
        if (!staticClass.IsRegistrationNumberValid(this.Value))
        {
            yield return new ValidationResult("An error occured");
        }
}

オプション 3: カスタム検証属性を作成します。

前述のValidationAttribute ように、この記事に示されているようにから派生させることにより、カスタム検証属性を作成できます。

IvalidatableObjectインターフェイスとカスタム検証属性のどちらを選択するかは、通常は好みにIValidatableObject依存しますが、検証が複数のプロパティに依存する場合 (たとえば、ある日付が別の日付の後にあるかどうかを確認する場合) は、インターフェイスが勝つケースの 1 つです。

オプション 4: サービス層で検証します。

最後に、検証がデータベースからの他の情報に依存している場合は、サービス レイヤーによる検証に関するこのチュートリアルを参照してください。この記事は完璧ではありません (サービスとコントローラーが少し密結合しすぎています) が、良いスタートであり、いくつかの変更により、非常に透過的でユーザー インターフェイスにデータベース検証エラー (主キー違反など) を渡すことができます。 -優しい方法。

おそらく、オプション 2、3、および 4 を組み合わせて使用​​することになります。最初のオプションを使用すると、コントローラー メソッドがより複雑になり、検証ロジックを他の場所で再利用することが難しくなるため、可能であれば最初のオプションを使用することは望ましくありません。

私のアドバイスは次のとおりです。

  • ユーザー入力の整合性を検証する場合 (たとえば、日付が正しい形式であることを確認する場合) は、IValidatableObjectインターフェイスとValidationAttributeクラスを組み合わせて使用​​します。
  • ドメインの整合性を検証する (重複するエンティティが入力されていないこと、またはエンティティ間の関係が定義されていることを確認する) 場合は、サービス レイヤーで検証を実行します。 
于 2013-04-16T18:33:17.240 に答える