ViewModel就是給View用的Model,什麼?ViewModel就是給View用的Model(又重複一次XD),在之前我們講的Model都是透過EF產生出來的實體類別,而在使用Scaffold產生的程式碼與檢視時,我們就已經選定Model了,詳細可參考Day22
但如果頁面同時想要顯示兩種實體類別的資料要怎麼辦,一個View只能搭配一個Model來使用阿!為了解決這個問題ViewModel就產生了,ViewModel就是專門給View呈現資料用了,除此之外它沒有任何作用。
接續前幾天的專案,我們來看一下,在新增完使用者與多筆Email之後,想在Details頁面同時顯示User資料以及Email資料要怎麼做
原始的Details Action 程式碼如下,可以知道抓到User這筆之資料之後,直接透過return View將user類別的資料傳入,若不了解Controller是如何傳值給View可以參考這篇
原始的Details檢視畫面如下,因為要接收由Action傳過來的資料,所以在第一行要使用@model宣告與Action同類別的Model
我們先來看一下如果不透過ViewModel要怎麼做
在View裡面搭配@foreach將值撈出來,不過這邊需要特別注意,因為這邊不是強型別,所以當然沒有自動提示可以用,必須非常小心字有沒有打錯,如果不小心打錯也只能等到執行時期也會發現,除非是傳一些很不重要的字串,不然我平常其實也不太喜歡使用ViewBag與ViewData
2.在Action內建立型別為UserDetailViewModel 的model,並將model.User與model.EmailList的值設定好,最後傳給View
3.在檢視這邊也要改成同名的UserDetailViewModel ,就在此時,Email就有強型別可以用了!有錯字也會馬上提示,不過比較麻煩的是要將之前使用User類別作為Model的寫法做一下修正,例如下圖的第6行與第9行
說到這邊可能對ViewModel還沒有什麼感覺,不過伴隨著專案持續開發,畫面呈現的資料日趨複雜的時候,千萬不要忘記ViewModel這個好幫手喔,例如在搜尋畫面就常常搭配ViewModel來使用,因為一個頁面中就至少會包含:關鍵字、頁碼、筆數、搜尋結果,這些如果沒有使用ViewModel並透過強型別來開發,真的會寫到頭昏腦脹。
另外ViewModel就只是一個為了呈現資料所產生的Model,除了設定屬性之外,就不要再寫其他的Code在裡面了,像我的第一個MVC專案,我就把全部的方法寫在ViewModel裡面,除了程式碼長得很噁心之外也不易維護(沒辦法誰叫當時不好好念書,正確來說是忙到沒時間唸阿,一堆藉口XD)
如果不知道程式碼要放哪,千萬不要放在ViewModel裡面,MVC裡面還有其他分層架構的觀念,將程式碼抽出或細分出來,例如Repository(處理資料庫操作)或Service(處理商業邏輯),因為這次鐵人賽定位在基本觀念的分享,就沒有對於這部分有詳細的介紹,有興趣的人再Google囉