2011-01-10 8 views
15

MVCでモデルを表示するこのアプローチを使用します。http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/29/how-we-do-mvc-view-models.aspx妥当性検査を継続する方法DRY?

私の心の中で未解決の質問を残します。だから私はそれがクリアされた時間です。

ドメインプロパティをdtoにマップするために自動マッパーを使用している場合、保存されているドメインエンティティにマップされている場合、ドメインレイヤーが一連の検証ルールを返すことができます。

しかし、DRYクライアントの検証を有効にしてモデル状態にエラーを追加する方法がないため、ビューモデルの正しいプロパティに対応していません。

乾杯

+1

良い点。私はこれを解決しようとする私の最後のカップルの質問でこれをしました。 – nick

答えて

11

私はいくつかの興味深い反応と関連する質問が見つかりました:私はこのことについて考えてきた、とのように、それは我々がサーバー側で持っている状況に似ている

Mapping Validation Attributes From Domain Entity to DTO

をクライアント側の検証が含まれます。 (例えば、NHibernate ValidatorとjQuery.validateの両方を使用するなど)。

最近では、サーバー側の検証が完全に行われている必要があり、クライアント側の検証を追加することは、アプリケーションをより使いやすいようにするためのオプションです。以前はクライアント側の検証を手動で実装する必要がありましたが、ユーザビリティのメリットがあるため、作業の重複を受け入れました。

私がここで扱っていることは非常に似ていると主張したいと思います。ドメイン層にの検証が必要です。消費アプリケーションに依存して、常に検証自体を追加することはできません。

DTO /ビューモデルで検証を追加するオプションがアプリケーションにあります。例外をスローする可能性があるドメインに到達させるのではなく、あまり有用でないエラーメッセージを表示するのではなく、ビューの検証エラーを処理する方が便利なためです。要点は、ドメインの観点からは、これが行われていることに依存していないことです。あなたのシステムには自信があります。なぜなら、悪いデータが通過するかどうかを知っているからです。あなたのモデルはそれをキャッチします。

クライアントサイドのコード(ASP.Net MVCのModelValidatorProviderなど)からクライアントサイドのコードを生成するために、多くの作業が自動化されているため、クライアント/サーバーのケースは最近問題になりません。より多くの人々がビューモデル/ DTOを使うようになるにつれて、ドメイン検証をDTOに自動的にマッピングするための類似のソリューションが見られるようになります(it's already happening with AutoMapper)。

だから要するに、私の(実用的ではなく、理想的な;))答えは:

は、今のDRYの違反を受け入れ、両方の場所で検証を行うと、それを自動化することを目指すプロジェクトに貢献しよう将来的に

+0

私は答えとしてこれを与えています。なぜなら、トレードオフを非常によく強調し、普遍的な完璧な解決法はないからです。 – nick

2

一般的なアプローチは、典型的には、データのアノテーションを使用することによって、あなたのビューモデルで、すべての検証を置くことです。 MVCを使用すると、データアノテーションからクライアント側(JavaScript)の検証を自動的に生成できます。かなり乾燥しています。

コントローラのポストアクションは、ビューモデルを取り込み、IsValidプロパティをチェックします。このように、あなたは同じコードで、クライアントとサーバーで検証する(または、私はデータの注釈の場合に属性を言う必要があります):

[HttpPost] 
public ActionResult ResetPassword(ResetPasswordViewModel viewModel) 
{ 
    if (ModelState.IsValid) 
    { 
    // convert to dto/entity and pass to next layer 
    // redirect to success page 
    return RedirectToAction("ResetPasswordSuccess"); 
    } 
    // display original view which will display error messages 
    return View(); 
} 

だけだけでコントローラのアクションテイクを持つことにより、これを追加しますviewModelをパラメータとして使用すると、デフォルトのMVCモデルバインダは自動的にビューモデルを検証し、ビュー内にエラーを表示するために使用されるModelStateエラーコレクションにエラーを追加します。

+2

モデルとVMで検証する必要があるため、どちらも乾いていません。また、VMに検証を追加するだけなので、モデルでビジネスルールを強制することもできません。 – nick

+0

あなたは基本的に、あなたのドメインがあなたのウェブアプリケーションによって消費されることを設計意思決定したと言いますが、あなたのウェブアプリケーションの開発者はドメインエンティティではなくビューモデルを使用してCRUDアクションを実行する必要がありますか? –

+0

つまり、開発者がそのように使用しないことがわかっているため、ドメインモデルが悪いデータに対して善良であることに同意しますか? –

5

他のビュー固有のフィールドとともにViewModelのプロパティとしてモデルを配置することをお勧めします。そうすれば、バインディング時にMVCによって検証され、MVCでバインドされていないときにバックエンドで検証できます。このようにして、クライアントの検証がMVCによって提供され、ビューに直接結び付けられていない検証オブジェクトでクリーンなモデルが得られます。

public class MyViewModel 
{ 
    public MyModel MyModel {get;set;} 
    public bool IsSomethingAllowed {get;set;} 
} 

public class MyModel 
{ 
    public int Id {get;set;} 
    [Required] 
    public string Name {get;set;} 
} 
+1

これは私のチームが決定した規約です。私たちが取り組んでいるプロジェクトでは、疎結合のビューモデルのためにDRY検証を失うことは、トレードオフの価値がありません。効率が悪く、エラーが発生しやすくなります。 – nick

+1

ドメインエンティティの使用に問題があります。例えば(1)タイプが正しくない場合有効な整数ではありませんか?ドメインエンティティで行った検証はヒットしません。モデルのバインディングは失敗し、一般的なメッセージが表示されます。ビューモデルでは、すべてのプロパティにstringを使用してモデルのバインディングが確実に行われ、ビューモデルが有効な整数かどうかを確認してユーザーにカスタムエラーメッセージを表示できます。 (2)検証メッセージにリソースファイルを使用している場合、ドメインオブジェクトはリソースファイルdllを参照する必要があります。とても素敵ではありません! –

+0

あまりいいですね。私は同意します。しかし、モデル・レイヤーにビジネス・ルールを適用するかどうかを決めますか?これは主なトレードオフのようです。しかし、これを指摘してもいいですね。 – nick

関連する問題