20

次のフォルダーを含む asp.net-mvc Web サイトがあります。

  • コントローラー
  • スクリプト
  • ビュー
  • ビューモデル
  • モデル
  • ドメインモデル

私は今、このビジネス ロジックとデータベース アクセス コードとデータの多くに別の .net アプリ (Windows コンソール アプリなので Web ではありません) にアクセスしたいので、MVC プロジェクトの外にあるものをできるだけ削除するようにリファクタリングしています。コードをこの他のソリューションと共有できるように、ソリューション内の他のプロジェクトに。

主な問題が 2 つあります。

  1. 私の主な問題は、ViewModel を生成するコードを配置する場所を見つけるのに苦労していることです。これは、コンソール アプリが同じデータを必要とする電子メールを送信するときに、このコードの多くをコンソール アプリで再利用したいからです。見る。

  2. もう 1 つの主な問題は、ビューモデルをインスタンス化する関数の多くが一連のデータベース アクセス コードで始まる場合に、内部にビューモデルを保持しながら、データベース アクセス コードを MVC プロジェクトから移動する方法を理解するのに苦労していることです。

これまでの詳細と私のプロセスの一部を次に示します。

ステップ 1 - DomainModel を別のプロジェクトに移動 - 成功

そのため、DomainModel プロジェクトの移動は簡単でした (これは、いくつかのビジネス ロジックが上にある多くの生のオブジェクトであり、それについては何も問題がありませんでした)。

ステップ 2 - コントローラーを間引く - 成功

コントローラーをできる限り間引いて、ビジネス ロジックや複雑なデータ アクセス ロジックを Models フォルダーに移動しました。モデル フォルダーを MVC プロジェクトの外に移動しようとすると、いくつかのことが壊れました。

ステップ 3 - Models フォルダーを MVC プロジェクトの外に移動しようとする - 苦労

コントローラーを間引いて、モデル クラスに移動し、ビューに戻す ViewModel を返すさまざまなコントローラー アクションをいくつか用意しました。このようなもの(私のコントローラークラスで):

 public ActionResult ApplicationDetail(int id)
 {
      AppDetailViewModel applicationViewModel = Model.GenerateAppDetailViewModel(id);
      return View(applicationViewModel);
 }

したがって、Model フォルダー内のファイルは ViewModel クラスに依存しています。複数の異なるコントローラーで使用される GenerateAppDetailViewModel() 関数を集中管理したいと考えています。また、私のコンソール アプリ (電子メールを送信する) では、たまたまあるビューにあるすべてのデータを取得したいことがよくあるので、私のコードはビューモデルも活用したいと考えています.. MVC プロジェクトから移動した場合その後、再利用できますが、依存関係の問題があると思います(明らかに、コンソールアプリで SelectListItem は必要ありませんが、再利用したいビューを生成するために必要な異なるデータのコンテナオブジェクトにすぎない場合もあります)

または壊れた別のことは、次への依存関係でした:

System.Web.Mvc

私は多くのコードを持っているので:

  1. データベース内のテーブルにクエリを実行する
  2. それをオブジェクトのコレクションに変換します(私はnhibernateを使用しています)
  3. これを、System.web.mvc の一部である DTO オブジェクト (ViewModels フォルダーにある) または SelectListItem オブジェクトのリスト (ビューにドロップダウンを設定するために使用) に変換します。

この依存関係を解消する最善の方法についての提案を探して、再利用のために MVC プロジェクトからできるだけ多くのコードを移動できるようにしたいと考えました。

問題は、ViewModel コードを Model フォルダーと別のプロジェクトに吸い込もうとすると、ViewModel クラスが多くの依存関係を持っているため、スタックすることです。

System.Web.Mvc

SelectListItem などが原因です。

2 つのビュー モデル フォルダーが必要です (1 つは特定の system.web.mvc 参照を持つ MVC プロジェクトにあり、もう 1 つは別のプロジェクトにありますか?)。SelectListItem への依存関係が競合を引き起こし続けているようです

私が見たほとんどの例では、このチュートリアルのように、ViewModels が System.Web.Mvc に依存しています。

私はこれらの質問を見てきました:

これらは一種の関連性がありますが、記載されている私の特定の全体的なリファクタリングの質問に答えているかどうかはわかりません。

4

5 に答える 5

1

拡張メソッドを使用してコントローラーでビューモデルを作成できます。

コントローラ:

 public ActionResult ApplicationDetail(int id)
 {
      var model = _serviceLayer.GetSomeModel(id); 
      var viewModel = model.CreateInstance(model);      
      return View(viewModel);
 }

SomeModelExtensionsこれを mvc プロジェクトで作成します

public class SomeModelExtensions {
      public AppDetailViewModel CreateInstance(this SomeModel model) {
           var viewModel = new AppDetailViewModel();
           // here you create viewmodel object from model with logic
           return viewModel;
      }
}
于 2013-07-04T06:21:03.350 に答える
1

一般に、モデルを再利用する必要がある場合に MVC アプリをレイアウトするときは、次のセットアップ/アーキテクチャを使用します。

MVC プロジェクト: Web 関連のすべて。ここで ViewModel を定義し、それらをドメイン モデルにマップします。

モデル プロジェクト: すべてのドメイン ロジックを含むクラス ライブラリ。

リポジトリ プロジェクト: DB とドメイン モデルにアクセスするクラス ライブラリです。

その仕組みは、MVC プロジェクトが (できれば注入された) リポジトリ ライブラリを使用してドメイン モデルを取得し、それを独自の ViewModel にマップすることです。

マッピングも分離したい場合は、他の人が提案したように(最終的にAutoMapperを使用して)マッピングレイヤーを別のプロジェクトに入れることができます。マッピング レイヤーはリポジトリ (およびドメイン モデル) を参照しますが、MVC アプリはマッピング レイヤーのみを参照します。

問題は、ViewModel を作成する際にマッピング レイヤーが System.Web.Mvc への参照を必要とすることであり、これを回避することはできません。これが、プロジェクトごとにマッピング レイヤーが必要であると他の人が言っている理由であり、私も同意します。

これを回避する良い方法は、一般的なケース (電子メールなど) 用に定義されたマッピング クラスを使用して、さらに一般的なマッピング レイヤーを用意することです。次に、特定の子クラスで、特定のケース (System.Web.Mvc に依存するものなど) のマッピングを定義できます。

したがって、最終スタックは次のようなものになり、依存関係が下がります。もちろん、すべてがインターフェースベースでなければなりません。

    MVC App                      Console App
       |                            |
       |                            |
   MVC Specific Mapper         Console Specific Mapper
                 \               /  
                  \             /
                   \           /   
                   GenericMapper <- EmailMapper and EmailViewModel can be implemented here
                     |       |      
                     |       |
                Repository   |
                     |       |
                     |       |
                    DomainModels  

上記は簡単に解決できるものではありません。一般的なケースが 1 つまたは 2 つしかない場合、マッピングを分割する労力はおそらく価値がありません。そうすれば、汎用マッパーから下は System.Web.Mvc ライブラリから解放され、上では DB アクセス コードを忘れることができます (ある意味で、マッパーはアプリのリポジトリとして機能します)。

于 2013-07-10T10:24:05.887 に答える
0

MVC Web は、コンソール アプリ + 追加フィールドと同じデータを使用すると思いますよね?

では、Model からの ViewModel の継承についてはどうでしょうか。そうすれば、モデルを再利用して、必要に応じて ViewModel でカスタム フィールドを取得できます。

public class AppDetailModel
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }


    public class AppDetailViewModel : AppDetailModel
    {
        public string ViewProperty { get; set; }
    }
于 2013-07-10T03:46:17.780 に答える