20

私は、かなり標準的で適切に維持されたDDDパターンを使用してMVC2プロジェクトを継承しました。私は、DTO/ViewModelの議論全体についても多くのことを読んでいます。

現在、DTOはViewModelsのようによく使用されます。正直なところ、私たちが行っていることに違いはありませんが、サイトをアップグレードするときに適切なViewModelを使用したいと思います。

これが私の質問です:

現在、「ドメイン」プロジェクトのモデルはエンティティを保持し、DTOをコントローラーに返します。次に、そのDTOをViewModelにマップする必要があります。どこでこれをすればいいですか?

  • コントローラーで正しいですか?
  • ドメインプロジェクトでは?
  • 他の場所?

「Web」プロジェクトのビューと一緒にViewModelを保持しているので、ドメインプロジェクトでDTO->ViewModelを変換するのは間違っていると感じます。また、コントローラーでそれを行うのは間違っていると感じます。

他の人は何をしましたか?

編集:

この質問/回答は、コントローラーで処理することを提案します。確かにこれを考えすぎるのは簡単です。

4

4 に答える 4

18

DTOは通常、テクノロジー固有です。たとえば、.NETの世界では、DTOはシリアル化属性で装飾されている可能性がDataContractあります。DataMemberさらに、DTOは、それらを返すサービスとともに、ヘキサゴナルアーキテクチャの観点からドメインへのアダプターを形成します。ドメインをHTTPなどの特定のトランスポートテクノロジーに適合させるため、ドメインの外部に存在しますつまり、ドメインはDTOの知識を持ってはなりません。DTOは別のプロジェクトで定義する必要があります。サービスを含むプロジェクトには、ドメインオブジェクトをDTOにマップするマッピングコードが必要です。

ASP.NET MVCプロジェクトは本質的に類似しており、サービス/ DTO(またはドメインオブジェクトを直接)をプレゼンテーションテクノロジ、特にHTMLに適合させます。そのため、DTOはViewModelを認識してはなりません。代わりに、MVCコントローラーはDTOとViewModel間のマッピングを呼び出す必要があります。これはさまざまな方法で実行できますが、私が最も効果的に機能することがわかったのは、DTOを受け入れるViewModelのコンストラクターです。また、コントローラーアクションが、サービスに返送されるDTOの作成を保証する場合、ViewModelには、ViewModelに基づいてDTOを作成するためのメソッドを含めることができます。これには、実際のデータに最も近いViewModelのすべてのマッピングコード(情報エキスパートパターンのインスタンス)が含まれます。これを実装する別の方法は、次のようなものを使用することです。ボイラープレートコードを回避するために規則ベースのマッピングを使用するAutoMapper 。それを超えるものは、それが要求されない限り、私はやり過ぎだと考えます。

多くの場合、ViewModelはDTOと同じように見えますが、バインドと検証のためのASP.NETMVC固有の属性があります。これはDRYの違反のように見えるかもしれませんが、これらは実際には別個の責任です。

于 2012-08-09T00:14:41.113 に答える
6

まず、ビューには常に明示的なViewModelを使用し、DTOをビューまで渡さないでください。これはもう少し前もっての作業ですが、ビューで必要なデータをより正確に制御できます(EFのようなフレームワークが、使用する場合と使用しない場合がある大量の余分なデータをサイドローディングすることも防ぎます)

次に、この記事では、オーケストレーターのパターンhttp://www.simple-talk.com/dotnet/asp.net/never-mind-the-controller,-here-is-the-orchestrator/の概要を説明します。他のパターンですが、私はそのフォーマットが好きです。

基本的に、すべてのコントローラーに対してオーケストレーターを作成します。Orchestratorは、データ(通常、ViewModel、および必要なその他の基本的なデータ型、特にHttpContextからのデータ型)を取り込み、ViewModel(Viewに必要な場合、それ以外の場合は他の戻り型)を返します。

この形式には、コントローラーが必要とするHttpContextのものをモックすることなく、実際のロジックを簡単に単体テストできるという利点があります。

于 2012-08-08T22:39:20.040 に答える
4

専用のマッピングクラス/モジュールでやりたいことのように聞こえます。

私は個人的にコントローラーにマッピングサービスへの依存関係を与え、次に実際の変換をそれに委任してから、新しくマップされたビューモデルでビューを返します。

public class DemoController : Controller
{
    private readonly IMappingService _mappingService;

    public DemoController(IMappingService mappingService)
    {
        _mappingService = mappingService;
    }

    public ActionResult Stuff()
    {
        var vm = _mappingService.Map(yourDto);

        return View(vm);
    }
}
于 2012-08-08T22:33:05.967 に答える
1

優れたアプローチは、dtoをパラメーターとして持つ2番目のコンストラクターでViewModelのコンストラクターをオーバーロードすることです。これは、ビューモデル自体でマッピングを処理できることを意味します。これにより、マッピングサービスを設定しなくても、コントローラーをすっきりと整理できます。

于 2012-08-08T22:53:13.077 に答える