2017-02-11 20 views
2

私はMVC5を初めて使い、ViewModelsの使用を把握しようとしています。私の質問は、自分のViewModelのコントローラーでモデルクラスをインスタンス化する必要があるかどうかです。私は、請求書を整理するためのデータベースを作成しており、データベーステーブルにマップするCashモデルと、データを表示/編集するCashViewModelを持っています。ここでMVC5のViewModelでModelクラスをインスタンス化する必要はありますか?

は私のモデルである:ここでは

public class Cash 
{ 
    public int CashId { get; set; } 
    public decimal CashAmount { get; set; } 
    public int CashTypeId { get; set; } 
    public DateTime DateModified { get; set; } 
    public CashType CashType { get; set; } 
} 

は私のViewModelである:ここでは

public class CashViewModel 
{ 
    public int CashId { get; set; } 
    public decimal CashAmount { get; set; } 
    public int CashTypeId { get; set; } 
    public SelectList CashTypeSelectList { get; set; } 
} 

は私のコントローラです:

public ActionResult Create([Bind(Include = "CashAmount,CashTypeId")] CashViewModel cashVM) 
    { 
     if (ModelState.IsValid) 
     { 
      var cash = db.Cashes.Create(); 
      cash.DateModified = DateTime.Now; 
      cash.CashAmount = cashVM.CashAmount; 
      cash.CashTypeId = cashVM.CashTypeId; 
      db.Cashes.Add(cash); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 

     ViewBag.CashTypeId = new SelectList(db.CashTypes, "CashTypeId", "CashTypeName", cashVM.CashTypeId); 
     return View(cashVM); 
    } 

私は現金モデルのインスタンスを作成していますViewModelクラスをモデルクラスにマッピングします。これは正しいです? 1つのViewModelに複数の属性を持つ複数のモデルがあるプロジェクトを開始すると、すぐに手を抜けてしまうようです。

私が読んだすべての質問と記事は、あまりにもあいまいであるか、あまりにも細かすぎて、特定の質問には何も見つかりません。

+0

あなたの何が正しいか。 [MVCのViewModelとは何ですか?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc)を参照してください。しかし、 'ViewBag.CashTypeId = new SelectList(....)'を取り除き、 'cashVM.CashType = new SelectList(db.CashTypes、" CashTypeId "、" CashTypeName ");'(これは第4パラメータには注意してください) - ビュー内に '@Html.DropDownListFor(m => m.CashTypeId、Model.CashType、...) 'とする必要があります。 –

答えて

2

ViewModelsは基本的にビューとコントローラの間にDTOを提供することです。しかし、あなたのモデルは間違っているように見えます.CashTypeIdではなく、CashTypeのみである必要があります.CashTypeモデルでは、IdとCashには参照があります。両方を持つ問題は、それらが同期していないということです。実際にEFが信頼できるものを選んでいることを覚えていません。

それ以外はあなたが理解したようです。 ViewModelには、ビューをレンダリングする値と、クライアントが値を割り当てるためのCashTypeIdを持つSelectListがあります。プライマリエンティティにCashTypeIdがなければ、新しいCashTypeオブジェクトを作成し、適切なIDを割り当てる必要があります(Entity Frameworkの場合)。

最後のアドバイス1つ:コントローラでこれらのDB操作を実行しないでください。 repository patternをチェックし、それらの間にビジネスレイヤーを置くことさえできます。

+0

ありがとうございます。私はWrox Professional ASP.NET MVC 5の本をMVC Music Storeの例を読んで読んでいて、外部キーIDを使ってデータベースの外部キー関係を作成しています。私はちょうどいくつかのテストクラスであなたが言ったことをテストし、他のセットアップで外部キーの関係... TILを参照しているモデルを参照します。リポジトリをフォローアップするために、彼らは基本的なCRUD関数を持っていますが、正規化されたテーブルを更新するために、すべてのモデルにビューモデルデータをマップする必要がありますか? – Andy

+0

リポジトリはモデル/エンティティのみを処理する必要があります。 ViewModelはASP.NET MVCプロジェクトの外部に存在してはいけません。したがって、ViewModelをModelにマップする必要があります。私は個人的にそれを使用していませんが、それを助けることができるAutoMapperと呼ばれるパッケージがあります。 –

1

私はCashモデルのインスタンスを作成し、ViewModelクラスをモデルクラスにマッピングしています。これは正しいです? 1つのViewModelに複数の属性を持つ複数のモデルがあるプロジェクトを開始すると、すぐに手を抜けてしまうようです。

あなたの行っていることに何も問題はありません。ただし、ドメインモデルからビューのモデル(ビューモデル)にマッピングする場合は、ライブラリを使用してマッピングを行うことができます。私はAutoMapperを使用します。あなたは、この持っている想像して:あなたのApplication_Start() startメソッドで

public class Cash { 
    public string Prop1 { get; set; } 
} 

public class CashViewModel { 
    public string Prop1 { get; set; } 
} 

を、あなたはこのようなビューのためにあなたのモデルにドメインモデルからマッピングする方法AutoMapperを指示することができます。

protected void Application_Start() 
{ 
    // ReverseMap will do vice-versa mapping 
    // If property names are the same, then AutoMapper will take care of it 
    // for you. 
    Mapper.Initialize(x => x.CreateMap<Cash, CashViewModel>().ReverseMap()); 

    // Of course you will have many cases where the property names 
    // are different 
    // For that case you will need to do this 
    // Imagine your model has a property called Name and view model has 
    // FirstName 
    Mapper.CreateMap<CashViewModel, Cash>() 
      .ForMember(model => model.Name, map => map.MapFrom(vm => vm.FirstName)); 
} 

次に、あなたのコントローラであなたはビューモデルからドメインモデルに変換するにはこれを行います:

var model = Mapper.Map<Cash>(cashViewModel); 

このアプローチの美しさは、すべてのマッピングが1か所に収まることです。結論として、hereはあなたが探しているものの大部分をカバーする素晴らしい記事です。

関連する問題