HttpPostからデータを取得し、データベースからデータを取得するオブジェクトがあるとします。ModelBinderが、投稿から欠落しているデータのデータベース/リポジトリに移動できるようにしたいと思います。実際には、これは良い考えですか、それとも悪い考えですか。
6 に答える
この種のことについての私の考えが2010年初頭から進化したため、元の回答を編集することにしました.
私の最初の回答では、基本的に、本能的にこれを行うべきではないと言いましたが、理由を明確に説明できずにすべきではないと言うのは不快でした.
Model Binder の責任はユーザー リクエストを Request Model に変換することであり、リクエストから派生できるもの以外のデータを取得することは、この責任の範囲を超えているという理由で、これに反対することをお勧めします。
悪い考えだと思います。モデルバインダーの考え方は、リクエストからパラメーターを取得し、それらからモデルを作成することです。モデルバインダーが舞台裏でデータベースの詳細の一部を入力すると、パラダイムが破られます。必要な追加データをデータベースから直接明示的にフェッチすることで、コントローラーでデータベース呼び出しを公開したいと思います。頻繁に使用する場合、これをメソッドにリファクタリングできることに注意してください。
これはまったく問題ないと思い、常にこの手法を使用しています。
反対する唯一の議論は非常に衒学的であり、哲学をめぐる議論に相当します。私見では、「欠落している投稿データを埋める」コードを、ベースコントローラーのメソッドとActionFilterのメソッド、ModelBinderのメソッドとしてMVCアプリに入れることができます。それはすべて、誰がどの責任を負うかによって異なります。私にとって、モデル バインダーは、投稿された値からいくつかのプロパティを接続するだけではありません。
モデルバインダーでデータベース呼び出しを行うのが好きな理由は、アクション メソッドをクリーンアップするのに役立つからです。
//logic not in modelbinder
public ActionResult Edit( KittyCat cat )
{
DoSomeOrthagonalDatabaseCall( cat );
return View( new MODEL() );
}
対。
//logic in model binder
public ActionResult Add( KittyCat cat )
{
return View( new MODEL() );
}
MVC の本来の動作方法に違反しています。ModelBinder は、ビューから取得したデータからモデルをビンジングするためのものです。データベースから不足している情報を入力することは、コントローラーによって処理されることになっています。理想的には、これを行うために使用するのと同じデータ レイヤー/リポジトリ クラスが必要です。
コントローラーにある必要があるのは、このコードがビジネス ロジックであるためです。ビジネス ルールでは、一部のデータが欠落している可能性があるため、操作の頭脳であるコントローラーによって処理する必要があることが規定されています。
さらに一歩進んで、ユーザーが投稿していない情報を DB にログインしたり、欠落しているデータを取得してそれについて管理者に電子メールを送信するときに例外をキャッチしたいとします。これらをこの方法でモデル バインダーに配置する必要があり、ModelBinder が元の目的からますます歪んでいくため、ますます醜くなります。
基本的には、コントローラー以外のすべてを、純粋にコントローラーを支援するための特定の専門分野を実行する方法だけを知って、可能な限り愚かで専門的なものにする必要があります。
いいえ、違います。
その理由は次のとおりです。コントローラーのアクションをテストするためのデータベースへの依存関係が作成され、抽象化するのは簡単ではありません。
大丈夫だと思います。データベースへの依存関係を作成する引数は、次の 2 つの理由から偽の引数です。
1- データベース アクセスは、リポジトリ インターフェイスを介して抽象化する必要があります。リポジトリ インターフェイスはドメイン モデルの一部であり、その実装はインフラストラクチャ/データ アクセス レイヤーの一部です。したがって、データベースへの依存はありません。
2- モデル バインダーとコントローラーはどちらも、ASP.NET MVC フレームワークを使用して実装されたプレゼンテーション レイヤーの一部です。コントローラーがリポジトリ インターフェイスを使用してデータベースにアクセスできる場合、モデル バインダーが許可されないのはなぜですか?
また、Model Binders からモデルに不足しているデータを埋めたほうがよい場合もあります。ビューにドロップダウン リストがあるシナリオを考えてみましょう。ビューが最初に読み込まれるときに、ドロップダウン リストにデータが入力されます。ユーザーはフォームを送信しますが、検証は失敗します。そのため、フォームを再度戻す必要があります。この段階で、ドロップダウン リストの [モデル] にリストを再入力する必要があります。コントローラーでこれを行うと見苦しくなります:
public ActionResult Save(DocumentViewModel viewModel)
{
if (!ModelState.IsValid)
{
viewModel.Categories = _repository.GetAll();
return View(viewModel);
}
}
ここでのカテゴリの初期化は醜く、コードの匂いのようだと思います。データベースから入力する必要のあるプロパティがいくつかあるとしたら? DocumentViewModel を引数として持つアクションが複数ある場合はどうなるでしょうか。この醜いステップを何度も繰り返さなければなりません。より良いアプローチは、Model Binder を使用してモデルのすべてのプロパティを入力し、それを Controller に渡すことです。したがって、コントローラーに渡されるオブジェクトは「一貫した」状態にあります。