15

私は最高の多層設計の慣行を遵守しようとしており、MVCコントローラがDAL(またはそれに関するIRepository)とやりとりしないようにしたいと考えています。適切なビジネスルールと検証を実施するには、ビジネスサービスレイヤーを通過する必要があります。検証 - ドメインモデルエンティティでさまざまな検証属性([必須]など)を使用してコントローラで検証を実行したくないのは、フロントエンドでこの問題が発生するためです。このサービスは、WPFのフロントエンドを通じて実装することもできます。MVC検証 - サービス層でDRYを維持する - ベストプラクティスとは何ですか?

私の検証は私のサービス層で行われているので、値をUIに戻すためのベストプラクティスは何ですか?私は失敗したかどうかを知る必要があるので、私は 'void addWhatever(int somethingsID)'を望んでいません。ブール値でなければなりませんか? Enumでなければならないのでしょうか?例外処理を利用すべきですか?または、モデルオブジェクトに検証属性を付加するときにMVCで使用されるものと同様のIValidationDictionaryオブジェクトを返しますか? (後で必要に応じてUIのアダプタパターンを使用することができます)

コントローラからサービスレイヤに自分のエンティティを渡し、検証/データパーシスタンスが失敗したかどうかを確認したいと思います。また、検証に失敗した可能性のあるフィールドごとに適切なエラーメッセージを表示するビューを返す必要があるという事実を忘れたくはありません(私はできるだけ痛みのない状態にしておきたい)。

私にはいくつかのアイデアがありましたが、そのすべてが正しく感じられません。答えにはビュー固有モデルのエンティティが含まれているように感じますが、これは処理しなければならないマッピングの問題全体につながります。ベストプラクティスとは何ですか?

答えて

17

私が知っているように、MVC検証はDRYに違反しているようですが、現実には、ほとんどの(非自明な)アプリケーションではそうではありません。

なぜですか?ビューの検証要件は、ビジネスオブジェクトの検証要件とはしばしば異なるためです。ビューの検証は、ビジネスモデルが有効ではなく、特定のビューが有効であることを検証することに関係しています。

時にはそれらの2つは同じですが、ビジネスモデルを有効にする必要があるようにアプリケーションを構築する場合は、このシナリオに自分自身をロックしています。オブジェクトの作成を2ページに分割する必要がある場合はどうなりますか? Webサービスにサービスレイヤーを使用することにした場合はどうなりますか? UIをビジネス層の検証シナリオにロックすることで、あなたが提供できるソリューションの種類が大幅に減ってしまいます。

ビューは、入力の検証であり、モデルの検証ではありません。

+0

これはかなり古い質問ですが、私はそのテーマについて少し説明したいと思います。 'username'は15文字を超えてはならず、一意でなければならないことを検証する必要があるとします。コントローラーで15文字の制限が発生し、サービスで一意性が確認されますか? – Aquillo

+0

@Aquillo - いいえ、両方の場所で両方を検証します。この回答は、一般的なビューと検証についてのものであり、特定のアイテムに関するものではありません。 MVCはプロパティではなく「モデル」を検証し、0以上の検証を持つことができる0以上のプロパティでモデルを構成します。 MVCは「このモデルは有効ですか」としか言いません。 –

4

Modelクラスをデータアノテーションで飾ることで、組み込みのMVC検証を利用することをお勧めします。これはビジネスルールの処理と検証とは異なる基本的な入力検証のためのものです。データ注釈は、消費者が意識しているが、消費者の使用方法を理解していない消費者に悪影響を与えないような、あらゆる消費者にとって有用であるため、優れています。

ビジネスルールとデータアクセスを抽象化するためにサービスレイヤーを使用することは正しいと思います。

  1. voidまたはprimativesの代わりにXXXResultオブジェクトを返します。コントローラとサービスの間のやりとりを強化するために、いくつかのことを行うことができます。あなたのサービスメソッドがAddProductの場合は、AddProductResultまたはより広範なProductServiceOperationResultを返します。この結果には、成功/失敗インジケータと追加情報が含まれています。

  2. WCFを使用している場合は、Fault Contracts and Exceptionを使用してください。

は私の典型的なMVCアプリケーションソリューションは、次のようになります(ほとんどの層によって参照プロジェクト、)

  • MVC Webサイトプロジェクト
  • xxx.Model
  • xxx.Services(プロジェクト)
  • xxx.DataAccess(プロジェクト、時にはサービスとマージ)
  • その他必要に応じて

幸い!

6

これは私のやり方です。

ビジネスルール/検証ルールに失敗した場合、例外をスローします。独自の検証を作成し、検証エラーの詳細を保持するいくつかのプロパティを追加します(たとえば、検証エラーがあるプロパティとメッセージは何か)。

次に、例外の拡張メソッドを作成します。 ModelStateへのエラーの詳細(私はSteve Sandersonsより優れた「Pro Asp.Net MVC 2 Framework」の本からこのアイデアを得ました) - これを正しく行うと、MVCは無効なフィールドを強調表示し、UIのエラーを表示します。

は、その後、あなたのコントローラは、これをyということを意味この

try 
{ 
    Service.DoSomeThing(); 
} 
catch (Exception err) 
{ 
    err.CopyTo(ModelState); 
} 

のようなものが含まれています私たちのビジネスルールと検証は現在あなたのサービス層にあり、これを再利用することができます。

ドメインオブジェクトをビューに渡すのではなく、ビューにDTO /ビューモデルを渡し、ドメインオブジェクトをDTOおよびその逆にマッピングすることも検討してください。

次に、DTO /ビューモデルはMVCレイヤーに置くことができ、検証属性でこれらを飾り、コントローラーにこれらをビューに渡すことができます - 組み込みのMVC検証を使用します。

複雑なプロジェクトの場合、UIの最後に必要な検証は、ビジネスルールの終了時に必要となるものと若干異なる場合があります。

AutoMapperと呼ばれる良いライブラリがあり、定型コードをあまり使わずに、ドメインオブジェクトからDTOに(またはその逆に)簡単にマッピングできます。

+1

ええと、無効なデータが「例外的」で、例外的な価値があるかどうかはわかりません。なぜ結果を返すか、組み込みの検証インターフェイスを使用することで例外を選択するのですか? –

+3

私は、MVCレイヤのバリデーション_is_ exceptionalによってキャッチされず、セリスレイヤによってキャッチされた無効なデータが多いことに同意します。私は事実の検証側にNHibernate.Validatorを使用しています。データレイヤーには例外がスローされます。私は、MVCレイヤーに組み込みの検証インターフェイスも使用しています。 MVCレイヤーは、組み込みのデータアノテーションを使用して入力エラーを捕捉する必要がありますが、無効なデータがMVCレイヤーを通過した場合、サービスレイヤーは例外 – StanK

+0

をスローします。個人的には、私はそんなことはしませんが、あなたの明確化にメリットがあります。 –

2

ここでの問題は、サービスレイヤでの検証ですが、その情報をWebアプリケーションに「バックアップ」する方法です。 サービスが有効であれば、依存関係注入のアイデアが明らかになったので、ここで少し似たようなことがありました。たとえば、IValidateableObjectが実装されていれば、呼び出すことはできません。私は以前このことを知ってませんでしたが、ModelValidator クラスを使用することで、何がバリデータを書き込むための 非常に強力な方法であることが表示されます。

オプション3:直接サービス)

アプローチを採用しました対応するModelValidatorProviderを返します。

ASP.NET MVC 3: Validating model when information external to the model is required

だから、基本的には、明示的なサービスロケータコールする必要なしに、MVCによって解決される(その後、あなたのサービス層になります)バリデータを注入しています。

0

実際には、いくつかのレイヤー(クライアント側、コントローラ側のサーバー側またはそれに相当するサーバー側、さらにはビジネス層内)で検証を繰り返し実行することは悪いことではありません。それはあなたのコードをいくらか分離します。理想的には、それらを1か所に記述するだけでよいが、時にはこれは不可能である。データアノテーションを使用しないことで、クライアント側の検証を行う場合は、本当に自分自身を難しくしていますか?そのようです。

とにかく、過去に非MVCアプリケーションで行ってきたことは、ほとんどのアクションメソッドがステータス(成功、エラー、警告)と検証エラーのリストを含むResponseオブジェクトを返すことです。その他のプロパティが必要です。

あなたはIValidateableObjectインターフェイスを活用することができますが、これはやはりASP.net固有のものにいくらか関係しています。おそらく、あなたの応答オブジェクトを消費し、DataAnnotation固有のエラーに変換することが妥協であろう。

1

このシナリオでは、スティーブンアドバイスは完璧です。現在、私は非常に大規模なMVC 3.0アプリケーションをSOAに取り組んでいます。他のことも関係しています。だからレスポンスでは、必要な情報をすべて記入し、それらをあなたの見解に示すことを望みます(もちろんコントローラが指示します)。お役に立てれば。

関連する問題