iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
自我挑戰組

用 30 天和 ASP.NET Core 打造一個活動報名管理系統系列 第 13

活動報名管理系統:Day13 ViewModel, AutoMapper

  • 分享至 

  • xImage
  •  

前言

先前我們已經用 Scaffolding 建立簡易的 CRUD 功能,不過可以發現,像是 Create 時,理應不需要填寫 CreateUser, CreateTime, UpdateUser, UpdateTime 的欄位,這時候我們該怎麼辦才好呢? ViewModel 就可以派上用場了

ViewModel

ViewModel 就像是針對不同的 View 所建立的 Model,它可以用來與 Controller 及 View 之間傳值,並且是強型別的方式,避免使用 ViewData、ViewBag 弱型別會導致型別錯誤的問題發生。

且 ViewModel 也能協助我們將兩個不同 Model 結合起來,e.g. Events 和 EventsInfo,這在後續會實際撰寫到。

在前言提到,CreateUser, CreateTime, UpdateUser, UpdateTime 的欄位我們是不需要自行填寫的,且 UpdateUser, UpdateTime 更是不會在新增頁面就儲存這兩個欄位的值到 DB,所以我們在 ViewModel 中就不會放 UpdateUser, UpdateTime

另外有個 CategoryId 的欄位,先前我們有設計了一個 EventsCategory 的 Model 與 Table,不過現在我們先為了方便測試,就先使用 enum 的類別來建立下拉選單與傳值給 CategoryId

EventsCreateViewModel

其實就只要把原本的 Model 複製過來,大部分就完成了,只是可以看到我多新增了 EventsCategoryEnum 這一個 Field。

EventsCategoryEnum

View

在 View 的第一行開始通常會是指定這一個 View 要接收哪一個 Model,在原本 Events 的 Create.cshtml,Model 是指定為 Events,此時我們要更改為 EventsCreateViewModel

另外也可以看到參考了 EventsSystem_iThome.Enum,因為下拉選單會參考 EventsCategoryEnum 類別,並使用 Tag Helper 做出下拉選單。

Model 指定為 EventsCreateViewModel 後,可以發現 UpdateUser, UpdateTime 的部分會發生錯誤,這是因為 EventsCreateViewModel 內沒有這兩個欄位,所以無法指定。

而我將 CategoryId 的 Code 也移除了,替換的是 Enum 的取值:

Controller

Scaffold 的 Controller,在 Model Binding 預設是產生弱型別的 Binding(Create()的參數),這樣的方法其實是不好的,且如果欄位增減,參數也需手動更新。

ASP.NET Core 提供了 Model Binding 的功能,Action 的參數只要指定好(e.g. 型別指定為 Model;或是 int Id,參數名設定跟 PK 一樣),那麼在 View 傳值到後端時,ASP.NET Core 會自動幫你將傳過來的值綁定在參數。

不過要傳到 DbContext 並新增資料至 DB 時,DbContext 接收的是原本的 Events Model 類別,EventsCreateViewModel 是無法直接放在 DbContext 的,此時需要將 ViewModel 的值都丟還給 Model。

可以 new Events 並將 EventsCreateViewModel 的 field 都一個一個指派到 Events,但這樣實在太慢了,此時有一個非常棒的套件可以來協助我們,AutoMapper。

AutoMapper

使用 Nuget 安裝 AutoMapper。

AutoMapper 讓我們可以用幾行的 Code 就做到 ViewModel 與 Model 間的欄位傳值,首先建立一個對應的型別定義 MapperConfiguration,在 <> 的左方為來源型別,右方則為目的型別,左方會放置 ViewModel,右方則是 Model。

接著實體化對應器 mapperConfig.CreateMapper();,實體化後使用 Map() 並先指定目的型別(Events 這一個 Model),並將 EventsCreateViewModel 放在參數中,如此就完成了 ViewModel 與 Model 間的對應,現在 Model 的 Field 已經都存好值了。

此時將對應完的 events 放到 DbContext,就可以執行新增的 Function 了!

本日結語

ViewModel 提供了更輕量化且更有彈性的 View 的傳值中介,ViewModel 與 View 一樣,它不該放置任何邏輯與其他方法,越單純越好。

AutoMapper 為 Model 間的對應減少了非常多的 Code,不需要寫很多個 A = B 就可以完成對應,我認為是一個在使用 ASP.NET Core 開發程式時,必須要安裝的套件。

Reference

[鐵人賽Day11] ASP.Net Core MVC 進化之路 - View(1) / 資料傳遞及Razor語法
ASP.NET MVC 的 ViewModel - 基礎篇
列舉類型 (c # 參考)
Get Int Value From Enum in C#


上一篇
ASP.NET Core - 活動報名管理系統:Day12 Life Cycle 生命週期
下一篇
ASP.NET Core - 活動報名管理系統:Day14 活動列表頁調整
系列文
用 30 天和 ASP.NET Core 打造一個活動報名管理系統30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言