2011-10-12 12 views
11

検証を実行するためにモデル外部の情報が必要な場合、モデルを検証する良い方法はありますか?ASP.NET MVC 3:モデル外部の情報が必要な場合のモデルの検証

public class Rating { 
    public string Comment { get; set; } 
    public int RatingLevel { get; set; } 
} 

システム管理者は、その後のコメントが必要なRatingLevelsを設定することができます。たとえば、次のようなモデルを考えます。これらの設定は、設定サービスを通じて利用できます。

モデルを完全に検証するには、そのモデルの外部に情報が必要です(この場合は設定サービス)。

私はこれまで、次のと考えてきました:

  1. をモデルにサービスを注入します。DefaultModelBinderSystem.Activatorを使用してオブジェクトを作成し、通常の依存関係リゾルバを通過せず、新しいモデルバインダを作成せずにモデルにサービスを注入することはできません(それ以外の場合は、それについて行く)。
  2. サービスを注釈に挿入します。私はまだこれが可能であるとは思っていませんが、すぐに調査を行います。それはまだ不器用な感じです。
  3. カスタムモデルバインダーを使用してください。どうやら私はOnPropertyValidatingを実装して、カスタムプロパティ検証を行うことができます。私はまだそれを行う方法がわからないけれども、これは今のところ最も望ましいようです。

このタイプの検証には、上記の方法が最適ですか?

答えて

14

オプション1は適合しません。それがうまくいく唯一の方法は、サービスロケータのアンチパターンを介して依存関係を引き出すことです。

オプション2 は動作しません。 C#属性の要件のために、これがどのように可能であるかわかりませんでしたが、可能です。参照のため、以下を参照してください。

オプション3:私はこの先に知っているが、何のバリデータを書き込むための非常に強力な方法であるように思われることはありませんでしたModelValidatorクラスとそれに対応するModelValidatorProviderを使用します。

まず、カスタムModelValidatorProviderを作成します。

public class CustomModelValidatorProvider : ModelValidatorProvider 
{ 
    public CustomModelValidatorProvider(/* Your dependencies */) {} 

    public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context) 
    { 
     if (metadata.ModelType == typeof(YourModel)) 
     { 
      yield return new YourModelValidator(...); 
     } 
    } 
} 

ASP.NET MVCのIDependencyResolverはとても限り、それはあなたのIoCコンテナに登録されていて、あなたが何かをする必要はありませんが、上記のプロバイダを解決しようとしますelse。そしてその後ModelValidatorは:プロバイダとして

public class EntryRatingViewModelValidatorMvcAdapter : ModelValidator 
{ 
    public EntryRatingViewModelValidatorMvcAdapter(
      ModelMetadata argMetadata, 
      ControllerContext argContext) 
       : base(argMetadata, argContext) 
    { 
     _validator = validator; 
    } 


    public override IEnumerable<ModelValidationResult> Validate(object container) 
    { 
     if (/* error condition */) 
     { 
      yield return new ModelValidationResult 
       { 
       MemberName = "Model.Member", 
       Message = "Rating is required." 
       }; 
     } 
    } 
} 

IDependencyResolver介して取得され、プロバイダは、私は簡単に依存性を注入し、必要な検証を実行することができた返さModelValidator Sを完全に制御しています。

+0

私はMVC5を使用していますが、私はまだそれがまだ関連していると思う。あなたは、 "MVCのIDependencyResolverはプロバイダを解決しようとします"と言いました。しかし、プロバイダをIoCコンテナにどのように登録しますか? (私の場合、統一)。 – Ben

1

サービスから返された値に基づいてモデルのクライアント側とサーバー側の両方の検証が必要な場合は、2を選択します。サービスを注釈に挿入します。

私はthis question about adding validators to a modelへの私の応答でいくつかのサンプルコードを提供します。あなたの場合の唯一の追加ステップは、DataAnnotationsModelValidatorProviderを継承するクラスにサービスを注入する必要があることです。

0

IValidateableObjectを使用するだけで、その方法で検証が適切かどうかを判断し、そこにエラーを設定しますか?

How do I use IValidatableObject?

+0

モデルがそれ自身を検証するためには、設定サービスにアクセスする必要があります。私がサービスロケータのアンチパターンを使用していない限り、カスタムモデルのバインダを作成してモデルにサービスを注入する必要があるため、検証はできません。 –

4

あなたはfluent validationを試みることができます。これはasp.net mvcとDIをサポートしているので、バリデーターに外部サービスを注入できます。

+0

彼らは本当に良い仕事をしたようです。リンクありがとう! –

関連する問題