[MVC] 適當的建立一個ViewModel,來讓Controller的程式更好維護

  • 28779
  • 0
  • MVC
  • 2012-02-25

[MVC] Model?我比較喜歡叫它ViewModel

這篇純粹是個人工作上的感覺,沒啥絕對性。

 

在MVC的架構中,我們都知道Model跟View有著曖昧的密友關係,

不過有時候在一個View的呈現上可能會使用多的Model組合而成的資料,

這時如果我們把組合Model的邏輯在Controller端硬兜好的話,

那麼Controller的Code就會變的相當多且複雜。

 

我用下方的例子作說明:

場景:

有一個極簡單的UI畫面須要組合Person和ContactMech兩個Model來呈現個人資料,

建立一個ViewModel來讓Controller端的程式Create,Edit,Show能好維護好閱讀。

 

首先會有兩個Model

   1:      //Table: Person 對應的Domain Class
   2:      public class Person 
   3:      {
   4:          public string Id { get; set; }
   5:          public string Name { get; set; }
   6:          public string Gender { get; set; }
   7:          public ContactMech ContactMech { get; set; }
   8:      }
   9:   
  10:      //Table: ContactMech 對應的Domain Class
  11:      public class ContactMech
  12:      {
  13:          public string Id { get; set; }
  14:          public string Mobile { get; set; }
  15:          public string Email { get; set; }
  16:      }

 

再來是我們的主角ViewModel,這邊的Model是一個非常充血的Model,因為他就只為了服務這些同值的View,越充血越好。

   1:   
   2:      // 一個充血型的Model,可以幫我們完成很多事情並讓Controller跟View節省很多Code
   3:      public class PersonInfoModel
   4:      {
   5:          // 呈現的View資料是來自兩個Model 定出View所需要用的相關屬性
   6:          public string Name { get; set; }   
   7:          public string Gender { get; set; }
   8:          public string Mobile { get; set; }
   9:          // 可以在屬性上設定相關的驗證如下:Email為必填欄位
  10:          [Required]
  11:          public string Email { get; set; }
  12:          public string PersonId { get; set; }
  13:          
  14:          public PersonInfoModel()
  15:          {
  16:              // 可利用建構子來初始化
  17:          }
  18:   
  19:          public PersonInfoModel(string id)
  20:          {
  21:              // 可利用建構子來初始化 如:
  22:              Show(id);
  23:          }
  24:   
  25:          public void Insert()
  26:          {
  27:              // 新增時要做的事
  28:          }
  29:   
  30:          public void Update()
  31:          {
  32:              // 修改時要做的事
  33:          }
  34:   
  35:          public void Save()
  36:          {
  37:              // 新增跟修改時的重複程式或共同邏輯可放這
  38:          }
  39:   
  40:          public void MapDomainToModel(string id)
  41:          {
  42:              // Show畫面呈現資料時要做的事,如把Model物件map到這個ViewModel上
  43:              Person person = personService.GetById(id);
  44:              this.PersonId = person.Id;
  45:              this.Name = person.Name;
  46:              this.Gender = person.Gender;
  47:              this.Mobile = person.ContactMech.Mobile;
  48:              this.Email = person.ContactMech.Email;
  49:          }
  50:      }
 
ViewModel做了這麼多事,那Controller需要幹什麼?

其實Controller光是要去處理View的Request就已經會讓它變的很複雜了,如:form submit,Ajax Get Post Load等等...

每一個request都要去幫它找合適的對象(Model,ViewModel,Json之類的),然後還要看要Return什麼東西給人家,

若在把ViewModel裡的邏輯都在Controller做的話,不僅寫的人會瘋掉連維護的人也會瘋掉

 

若以上方的ViewModel的方式的話,Controller就單純多了,如下

   1:      public partial class PersonInfoController
   2:      {
   3:          public ActionResult Show(string id, string cdts)
   4:          {
   5:              PersonInfoModel model = new PersonInfoModel(id);          
   6:              return View(model);
   7:          }
   8:   
   9:          public ActionResult Create()
  10:          {
  11:              return View();
  12:          }
  13:   
  14:          [HttpPost]
  15:          public ActionResult Create(PersonInfoModel model)
  16:          {
  17:              if (!ModelState.IsValid)
  18:              {
  19:                  return View(model); //// 不通過驗證
  20:              }
  21:              model.Insert();
  22:              return RedirectToAction("Show", new { id = model.PersonId }); 
  23:          }
  24:   
  25:          public ActionResult Edit(string id)
  26:          {
  27:              PersonInfoModel model = new PersonInfoModel(id);
  28:              return View(model);
  29:          }
  30:   
  31:          [HttpPost]
  32:          public ActionResult Edit(PersonInfoModel model)
  33:          {
  34:              if (!ModelState.IsValid)
  35:              {
  36:                  return View(model); //// 不通過驗證
  37:              }
  38:              model.Update();
  39:              return RedirectToAction("Show", new { id = model.PersonId }); 
  40:          }
  41:      }

 

這樣Controller的Code就乾淨清爽多了,也很容易的知道每個Action在幹什麼,

就算之後可以還會要求在多一個Copy的Action那麼,也只要Controller分配好Model的動作就可以迅速的完成這功能。

以上是個人寫MVC的偏好,感謝您耐心的看完了,希望有幫助到。