3

Service クラス内から検証を実行できるようにしたいと考えています。次のようなコントローラーアクションがあります。

public ActionResult Edit(Post post)
{
    if(!ModelState.IsValid)
       return View();

    _postDataService.SavePost(post);

    return View("Index");
}

_postDataService.SavePost() が無効なデータを保存できるという事実が気に入らず、モデルの検証を _postDataService.SavePost() メソッドに移動したいと考えています。私の質問は、これを行う最もエレガントな方法は何ですか? また、モデルの検証を Service メソッドに移動した場合、モデルのエラーをコントローラーに返すにはどうすればよいでしょうか? 最後に、データ アクセスが必要なため、電子メール アドレスの一意性などのモデル検証はどこに行くのでしょうか? 私が見たすべての同様の質問の中で、これを行う簡単な方法を提供するものはありません。

この解決策も検討しましたが、この記事は古く、最新ではないと感じています。

4

1 に答える 1

3

Post モデル/エンティティ クラスのプロパティに属性を設定して検証を行っていると思います。その場合は、次のようにしてサービス レイヤーで検証できます。

var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(post, 
    new ValidationContext(post, null, null), results, true);

これは基本的に、コントローラー/アクションの ModelState オブジェクトを検証および構成するときに、デフォルトのモデルバインダーが行うことです。

このアプローチの利点は、サービス層から検証エラーを返す必要がないことです。上記のコードを自動的に実行するには、デフォルトのモデルバインダーに依存するだけです。誰かが ModelState.IsValid をチェックせずにそのアクションを呼び出そうとした場合は、サービス メソッドで例外をスローして思い出させてください。

コメント後に更新

はい、私の答えでは、検証を 2 回行うことをお勧めします。

それについてどう思いますか?私は気にしない。MVC では Entity Framework 4.1 を使用し、MVC ではエンティティを使用しません。代わりに、automapper を使用して、エンティティを別のビューモデル レイヤーに DTO します。また、EF エンティティは ValidationAttributes で装飾されており、これは EF が DbContext.SaveChanges() 操作中に自動的に評価します。ビューモデル クラスのプロパティに非常によく似た検証属性を適用します。これは DRY とは思えないかもしれませんし、間違いなく重複していますが、場合によっては、UI 側の検証属性がドメイン モデルの検証属性と異なる場合があります。

サービス層では検証を行いません。私たちのサービス層は単なるアプリケーション フロー コーディネーターであり、ビジネス ルールには責任を負いません。ただし、アプリケーションでは検証が 2 回行われます。まず、ビューモデルの検証規則に対して、デフォルトのモデル バインダーによって。次に、トランザクションが EF になると、エンティティに対して検証が実行されます。したがって、実際には 2 つの別々のレイヤーを検証しています。

ただし、考えてみると、ここでは 2 つの異なる懸念事項に実際に取り組んでいます。UI で、MVC が検証メッセージをユーザーに表示するようにします。ModelState は、MVC 検証 (モデル バインディング / jquery / unobtrusive / client-validation / など) とうまく連携するため、これに最適です。

逆にドメインでは、データの整合性を保護し、ビジネス ルールを適用します。ドメインは、ユーザーへのメッセージの表示を気にしません。それが知っている限りでは、クライアントはマシン、WCF サービス、またはその他のものである可能性があります。ドメインの役割は、トランザクションが発生するのを防ぐことであり、(私たちの場合) 静かにクライアントを "操作" しようとするのではなく、例外をスローします。

于 2012-01-04T10:51:10.640 に答える