これが、入力画面をモデルに密結合してはならない典型的な理由です。この質問は、実際には月に 3 ~ 4 回、MVC タグに表示されます。前の質問を見つけることができればだまします。ここでのコメントの議論のいくつかは興味深いものです。;)
あなたが抱えている問題は、モデルの 2 つの異なる検証コンテキストを、多数のシナリオで失敗する単一のモデルに強制しようとしていることです。最良の例は、新しいユーザーをサインアップし、後で管理者にユーザー フィールドを編集させることです。登録時にユーザー オブジェクトのパスワードを検証する必要がありますが、ユーザーの詳細を編集する管理者にパスワード フィールドを表示しません。
これらを回避するための選択肢はすべて最適ではありません。私は現在 3 つのプロジェクトでこの問題に取り組んできましたが、次の解決策を実装することは決してクリーンではなく、通常はイライラします。私は実用的になり、他の人が行っている DDD/db/model/hotnessofthemonth の議論をすべて忘れようとします。
1) 複数
のビュー モデル ほぼ同じビューモデルを持つことは DRY 原則に違反しますが、このアプローチのコストは非常に低いと感じています。通常、DRY に違反するとメンテナンス コストが増加しますが、IMHO のコストは最も低く、大した額にはなりません。仮説的に言えば、LastName フィールドの最大文字数を頻繁に変更することはありません。
2) 動的メタデータ
MVC 2 には、モデルに独自のメタデータを提供するためのフックがあります。このアプローチでは、メタデータを提供するために使用するものは何でも、現在の HTTPRequest に基づいて特定のフィールドを除外し、したがって Action と Controller を除外することができます。私はこの手法を使用して、DB にアクセスし、DataAnnotationsMetadataProvider のサブクラスに、データベースに格納されているプロパティ ベースの値を除外するように指示するデータベース主導のアクセス許可システムを構築しました。
この手法はうまく機能していますが、唯一の問題は で検証することUpdateModel()
です。この問題を解決するためSmartUpdateModel()
に、データベースにもアクセスし、exclude string[] 配列を自動的に生成して、許可されていないフィールドが検証されないようにするメソッドを作成しました。もちろん、パフォーマンス上の理由からこれをキャッシュしたので、悪くはありません。
モデルで [ValidationAttributes] を使用し、実行時に新しいルールで置き換えたことを繰り返したいと思います。その結果[Required]
、ユーザーがアクセス許可を持っていない場合、User.LastName フィールドは検証されませんでした。
3) クレージーなインターフェースの動的プロキシー
私が最後に試したテクニックは、ViewModel のインターフェースを使用することでした。IAdminEdit
最終的に、 や などのインターフェイスから継承した User オブジェクトができましたIUserRegistration
。IAdminEdit と IUserRegistration の両方に、インターフェイスを使用した Password プロパティのようなすべてのコンテキスト固有の検証を実行する DataAnnotation 属性が含まれます。
これにはいくつかのハッカーが必要であり、何よりも学術的な課題でした。2 と 3 の問題は、この手法を認識できるように UpdateModel と DataAnnotationsAttribute プロバイダーをカスタマイズする必要があることです。
私の最大の障害は、ユーザー オブジェクト全体をビューに送信したくなかったため、動的プロキシを使用してランタイム インスタンスを作成することになりました。IAdminEdit
これは非常に xVal 固有の質問であることがわかりましたが、このような動的検証への道はすべて、内部 MVC メタデータ プロバイダーのカスタマイズにつながります。メタデータはすべて新しいものなので、現時点ではそれほどクリーンでシンプルなものはありません。MVC の検証動作をカスタマイズするために必要な作業は難しくありませんが、すべての内部のしくみに関する深い知識が必要です。