Razor Pages 實務上與 ASP.NET MVC 的差異-列表頁
- 2021-04-21
- 10793
- 0
- Razor Pages 與 ASP.NET MVC 的差異
情境解說
在資料庫中的資料表欄位會依據資料面來設計,但往往會與「顯示」「新增」「編輯」時所需的欄位不同,可能有多也可能有少,得過且過的開發人員會一股腦的都用 DB Model 來傳遞資料,但這是一種浪費也可能造成資安問題,依據我們開發 MVC 的習慣會建立稱為 View Model 的傳遞物件,本篇文章就來示範此情境在 ASP.NET MVC 與 Razor Pages 我們會怎麼做。
為了讓範例可以達到不用解釋的目的,我們將以會員註冊這大家都寫過的東西來做範例。
資料庫表單建立
public class Account
{
[Key]
public Guid Id { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[StringLength(1000)]
public string Password { get; set; }
[Required]
[StringLength(50)]
public string NickName { get; set; }
[Required]
[StringLength(300)]
public string Email { get; set; }
public bool IsEnable { get; set; }
}
在 .NET Core 開發人員可以使用Code First 的方式由程式建立出資料表,而這個建立的類別又剛好可以拿來當成 DB Model 建議各位開發人員真的要試試看。
View Model 建立
首先要開發的是帳號列表功能,在此案例中顯示給管理者看的帳號列表並不會將使用者的帳號[Name]與密碼[Password]顯示出來,為了節省資料傳遞通常會新增一個資料傳遞用的類別,並且只設定需要的屬性,而這個類別在 MVC 中稱做 View Model 。
public class AccountListViewModel
{
public Guid Id { get; set; }
[Display(Name = "暱稱")]
public string NickName { get; set; }
[Display(Name = "EMAIL")]
public string Email { get; set; }
[Display(Name = "啟用")]
public bool IsEnable { get; set; }
}
View Model 依據習慣取代配置原則都會加上 ViewModel 後綴
列表實做
既然我們都選擇了這個內建 DI 的 .NET Core 了,不免俗的先建立介面吧
public interface IAccountService
{
Task<AccountListViewModel> LookupAllDataAsync();
}
接下來就先使用各位都普遍熟習的 MVC 撰寫相關程式碼
public class AccountController : Controller
{
private readonly IAccountService _accountService;
public AccountController(IAccountService accountService)
{
_accountService = accountService;
}
// GET
public async Task<IActionResult> Index()
{
var source = await _accountService.LookupAllDataAsync();
return View(source);
}
}
MVC 與 RazorPages
前端的部分就不貼 Code ,我們單純點講後端就好,依據上面這些程式我們可以看到在 ASP.NET MVC 中我們的列表功能是由 DB Model, View Model, Service, Controller, View 結合成而這是我們開發 MVC 一直以來的習慣,至少分層三層,再視專案的需求增加 Service 等層,這樣的習慣在改成屬於 MVVM 的 Razor Pages 後會有什麼變化呢?
在 Razor Pages 的設計中每一個頁面都會有自己專屬的 Model ,稱為 Page Model 而此案例有實做 Service 層所以可以利用 View Model 來作為 Service 與 Razor Page 的傳遞物件,你可以發現當改用 Razor Pages 開發後 Service 層以上的東西還是可以保有 MVC 留下來的習慣,只有應用上的寫法不同,以下就是 Razor Pages 的寫法。
public class Index : PageModel
{
private readonly IAccountService _accountService;
public Index(IAccountService accountService)
{
_accountService = accountService;
}
public AccountListViewModel AccountList { get; set; }
public async Task OnGetAsync()
{
AccountList = await _accountService.LookupAllDataAsync();
}
}
MVC 的 Controller 繼承 Controller ,Razor Pages 的 Page 繼承 PageModel
在這裡你可以看到public AccountListViewModel AccountList { get; set; }
這行指令就是在 Index
這頁的 Page Model 建立了一個名稱為 AccountList
的屬性,型別是 AccountListViewModel
,在 Index
類別中擁有 OnGetAsync()
方法,我們在此方法中賦予 AccountList
屬性值,結束時您甚至不用 Return
就可以在前端頁面使用 @Model.AccountList
存取相關內容,這段 Code 有沒有好熟習?是不是和我們日常在設計 Class 一樣的自然、直覺。
如果還感受不到差異,不如再加上兩個常見的功能,分頁與搜尋吧。
實做分頁與搜尋後的差異
先來看看 MVC 版本的
public class AccountController : Controller
{
private readonly IAccountService _accountService;
public AccountController(IAccountService accountService)
{
_accountService = accountService;
}
// GET
public async Task<IActionResult> Index(int? p, string searchNickName, string searchEmail)
{
var source = await _accountService.LookupAllDataAsync(searchNickName, searchEmail, p, 20);
return View(source);
}
}
再來看看 Razor Pages 的版本
public class Index : PageModel
{
private readonly IAccountService _accountService;
public Index(IAccountService accountService)
{
_accountService = accountService;
}
public IPagedList<AccountListViewModel> AccountList { get; set; }
[BindProperty(SupportsGet = true)]
public int P { get; set; }
[BindProperty(SupportsGet = true)]
public string SearchNickName { get; set; }
[BindProperty(SupportsGet = true)]
public string SearchEmail { get; set; }
public async Task OnGetAsync()
{
AccountList = await _accountService.LookupAllDataAsync(SearchNickName,SearchEmail,P, 20);
}
}
在 MVC 中方法(Action)內所需要的參數要使用傳入的方式,而 Razor Pages 則是使用屬性的資料綁定,而且也同時支援參數的傳入方式,不過在我們開發 Razor Pages 的時候通常都會選屬性,單一頁面、單一功能需要的資訊都在同一個檔案,就和我們在設計類別是一樣的習慣一切都被封裝在一個 Class(Page)內,不會影響別人也不會被別人影響,到這裡你應該可以稍微有點感覺 Razor Pages 就和我們以前寫的 Web Forms 很像,一個前端頁面 *.cshtml 搭配一個後端程式 *.cshtml.cs ,但只有這樣絕對是不會讓筆者把主力框架從 MVC 改成 Razor Pages 的,下一章我們將會看到另一個實務上經常面對的議題,新增與編輯所需欄位不同在 Razor Pages 的表現。
回應討論