26

私は最近、Web 開発者として働き始めました。ASP .NET MVC 4 と NHibernate を使用しています。

私の職場では、ビューモデルを使用して、コントローラーとビューの間でデータをやり取りするように厳密に作られています。また、ビューモデルにはモデルのオブジェクトを含めることは想定されていません。コントローラーとビューの間の一種の層であることを理解しています。

しかし、モデルのオブジェクトをビューに直接送信できる場合でも (ほとんどの場合)、viewmodel クラスを記述するのは反復的で冗長であることがわかりました。

たとえば、注文を表示したい場合は、コントローラーのアクションでこれを行うことができます -

return View(Repository.Get<Order>(id));

しかし代わりに、ビューモデルを作成し、フェッチした注文を入力してビューに渡す必要があります。

ですから、私の質問は、モデルのオブジェクトをそのまま使用できる場合、ビューモデルを記述することはどのような目的に役立つのでしょうか?

4

4 に答える 4

18

小規模なプロジェクトの場合、その通りです。私はあなたの主張を聞いて同情します - しかし、特に大規模で複雑なアプリケーションでは、この単調で反復的な作業には十分な理由があります。

  • コントローラーのアクション内ですべての処理を実行することが不可欠です。ただし、指定した例では、Repository.Getメソッドは遅延評価されたオブジェクトを返す可能性がありIQueryableます。これは、ビューが評価されるまで DB がヒットしないことを意味します。さまざまな理由から、これは悪いことです。(回避策は、コントローラー内にいる間に呼び出すこと.ToListです)。
  • 「ビューにはプレゼンテーション以外のロジックを含めるべきではありません」および「ビューを信頼するべきではありません」(ビューはユーザーが提供する可能性があるため)。Model オブジェクト (アクティブな DatabaseContext にまだ接続されている可能性があります) を提供することにより、ビューはデータベースに悪意のある変更を加えることができます。
  • ビューの表示するデータは、常にモデルのデータと 1:1 でマッピングされるとは限りません。たとえば、ユーザーの詳細ページを考えてみましょう。

    ユーザーの EF モデル オブジェクトは、データベース内のエンティティを表すため、おそらく次のようになります。User { UserId, UserName, PasswordHash, PasswordSalt, EmailAddress, CreatedDate }「ユーザーの詳細」ページのフィールドは になりますがUser { UserId, UserName, Password, ConfirmYourPassword, EmailAddress }、違いがわかりますか? したがって、EF User モデルをビュー モデルとして使用することはできません。別のクラスを使用する必要があります。

  • モデル操作の危険性: ASP.NET MVC (またはその他のフレームワーク) に着信 HTTP POST 要求へのモデル バインディングを行わせると (上記のユーザーの詳細の例を取り上げます)、ユーザーはUserIdプロパティ値を偽造して誰のパスワードもリセットできます。 . ASP.NET はバインディング中にその値を書き換えます。具体的にサニタイズしない限り (これはとにかく個々の ViewModel を作成するのと同じくらい面倒です)、この脆弱性は残ります。

  • 複数の開発者がチームで作業しているプロジェクトでは、すべてが一貫していることが重要です。特注の ViewModel を使用しているページと EF モデルを使用しているページがあるというのは一貫性がありません。チームが意識を共有していないためです。同じ理由で、1 人の開発者は、ソース コードに過度の XML ドキュメントを入れなくても済む場合がありますが、チームの状況では、そうしないとバラバラになります。

あなたの場合、私があなたと共有するわずかな回避策がありますが、前提条件に注意してください:

  • あなたの意見は完全に信頼できます
  • ビューにはプレゼンテーション ロジックのみが含まれています
  • アプリケーションの大部分は CRUD です
  • ビューは各 EF エンティティ モデルと 1:1 で対応します (つまり、JOIN はありません)。
  • ビューは、複雑なモデル (つまり、オブジェクト グラフ) ではなく、POST フォームの単一の単純なモデルのみを扱います。

...次に、これを行うことができます:

  • すべての一方向の非フォーム関連データをViewDataコレクションに入れるか、 MVC 4 (ハードコアの場合はViewBagジェネリックにさえ) に入れます。ViewData<T>これは、HTML ページ タイトルを保存し、マスター ページとデータを共有する場合に便利です。
  • 完全に評価され、読み込まれたEF モデルをモデルとして使用しますView<TModel>

ただし、このアプローチは矛盾を引き起こす可能性があるため、注意して使用してください。

于 2013-01-20T09:13:52.447 に答える
4

ええと、私はあらゆる問題に対して実用的なアプローチが必要であり、そこにある純粋なアーキテクチャ標準に同意するだけではないと考え始めています。アプリは実際に実行する必要があり、多数のクライアント セットなどにサービスを提供する多くの開発者によって維持される必要がある場合があります。これにより、アーキテクチャが指示または駆動される場合があります。

  • ViewModel は、DomainModel (DataModel) とコードの残りの部分との間の懸念事項を分離したい場合に不可欠です。

モデル、ビュー、コントローラー間の依存関係が少なければ少ないほど、ビューやコントローラーなどのインターフェイス コントラクトを壊さずに DomainModel を変更するのが簡単になります。コードのリファクタリングはシステム メンテナンスの大きな部分を占めるため、私はこのアプローチが気に入っています。リファクタリングには、モデルのプロパティの単純なスペル ミスが含まれる場合があります。例えば。

  • ViewModel は、DomainModel とビューの間でデータを変換するために使用されます

Informix に格納されている日時の単純な例は、.Net DateTime に変換する必要があります。ViewModel は、この変換を行うのに最適な場所であり、あらゆる種類の望ましくない場所に変換コードを配置することを強制しません。

[何でも] 優れた設計の 1 つの属性は、システムの残りの部分にほとんどまたはまったく影響を与えることなく、実装の一部を交換または変更できることです。しかし、これを達成するには労力と時間がかかります。完璧なデザイン十分なデザインとの間の実用的なバランスを見つけるのはあなた次第です。

しかし、特定のパターンを使用する正当な理由は他にもたくさんありますが、結論としては次のとおりです。

ViewModel の使用を強制するものはありません。ASP.NET MVC は強制しません。あなたの中のプラグマティストからアドバイスを受けてください。

于 2013-01-20T09:24:58.493 に答える
3

ViewModelsと同じモデルを使用する場合、アプリケーションは非常に小さくシンプルで、CRUD操作のみが含まれている必要があります。ただし、大規模なチーム(2人以上の開発者がいる)で大規模またはエンタープライズアプリケーションを構築する場合は、依存性注入、サービス、リポジトリ、ファサード、作業単位、データアクセスオブジェクトなどの概念が必要です。

モデルとViewModel間のマッピングのニーズを簡素化するために、AutoMapperhttps://github.com/AutoMapper/AutoMapperを使用でき ます。

または、nugetInstall-PackageAutoMapperを使用してインストールします

于 2013-01-21T07:52:09.500 に答える