Razor Pages 實務上與 ASP.NET MVC 的差異-新增與編輯
- 2021-04-21
- 10087
- 0
- Razor Pages 與 ASP.NET MVC 的差異
以前 MVC 框架有人反應拆太細了,大多數專案其實不需要那麼龐大的架構,現在有了更聚焦更輕量化的 Razor Pages,或許對於我們是一個不錯的解法。
前情提要
延續上一篇的架構,繼續開發新增與編輯功能,在實務中新增與編輯所需的欄位往往不同,不會和範例一樣單純使用一個 View Model 就解決,為了這些不同有許多種作法,都能達到需求但也都有一些議題,以這次的例子會員註冊來說要填寫的欄位與編輯就不會是相同的,首先使用 MVC 的寫法來看看。
MVC 使用參數傳遞
註冊(新增)只需要填帳號[Name]、密碼[Password]、暱稱[NickName]、EMAIL 但如果直接使用 DB Model 會因為驗證而出錯,為了避開這問題,最直覺的寫法就是這樣
[HttpPost]
public async Task<IActionResult> Create(string name, string nickName, string password, string email)
{
if (ModelState.IsValid==false)
{
return View();
}
var newData = new Account()
{
Id = Guid.NewGuid()
, Name = name
, NickName = nickName
, Password = password
, Email = email
, IsEnable = true
};
await _accountService.AddAsync(newData);
await _accountService.CommitAsync();
return RedirectToAction(nameof(Index));
}
範例程式把會省略部分資料驗證與例外處理,範例可以省略,實務上你不可以省
MVC 使用 DB Model
上面的程式當然是可以正常執行的,但當一切都使用參數來傳,資料驗證的部分就需要手工處理,都已經使用了那麼強的框架還要自己來是很不明智的,為了讓資料驗證可以輕鬆自在點就會有開發者是這樣寫的。
[HttpPost]
public async Task<IActionResult> Create(Account model)
{
ModelState.Remove("Id");
ModelState.Remove("IsEnable");
if (ModelState.IsValid==false)
{
return View();
}
model.Id = Guid.NewGuid();
model.IsEnable = true;
await _accountService.AddAsync(model);
await _accountService.CommitAsync();
return RedirectToAction(nameof(Index));
}
不使用參數一個一個傳,而改成直接使用 DB Model 所以我們當初因為 Code First 所設定的驗證屬性自然就會生效,開發者是自己當然就很清楚知道 Account 中的 Id 和 IsEnable 兩個欄位沒有輸入的話會引發例外,因此就明確的使用 ModelState.Remove("Id");
來排除不想被驗證的欄位,排除後ModelState.IsValid
就不會因為這兩個欄位而驗證失敗了!但 [Id] [IsEnable] 兩個欄位不會讓使用者填,雖然沒驗證錯誤了但它們依然是空的,記得要自己把正確的值補上去。
MVC 使用 Create Model
這樣子看起來程式碼已經比第一版好,而且還擁有了資料驗證的功能,但其實這樣的寫法就是在系統中埋下一顆地雷,只要那一天對應的 DB Model 異動,多出了新的不可為空的欄位,我們的註冊功能就馬上死去,為了隔開它們的相依 Create Model 因應而生。
public class AccountCreateModel
{
[Display(Name = "帳號")]
[Required]
[StringLength(50)]
public string Name { get; set; }
[Display(Name = "密碼")]
[Required]
[StringLength(1000)]
public string Password { get; set; }
[Display(Name = "暱稱")]
[Required]
[StringLength(50)]
public string NickName { get; set; }
[Display(Name = "EMAIL")]
[Required]
[StringLength(300)]
public string Email { get; set; }
}
既然已經是客制化的 Create Model 了,當然就可以在這直接加上驗證所需的屬性,改用 Create Model 後程式碼就可以縮減成這樣
[HttpPost]
public async Task<IActionResult> Create(AccountCreateModel model)
{
if (ModelState.IsValid==false)
{
return View();
}
var id=await _accountService.AddAsync(model);
await _accountService.CommitAsync();
return RedirectToAction(nameof(Index));
}
改用 Create Model 後 Controller 的程式碼就會相對乾淨,介面接收的參數也由原本的 DB Model 改為 Create Model 隔離的狀況也比較好了,但回過頭來看,這樣的設計下我們開始會有許多因不同欄位而產生的 Create Model 最後很容易導致命名困難,每個名稱都開始模擬兩可,更慘的是每個檔案打開都長的大同小異,不仔細看還很容易改錯檔案… 那如果改用 Razor Pages 開發會有什麼不同呢?
Razor Pages 登場
首先還是要新增介面
Task AddAsync(Account newData);
你可以看到在 Razor Pages 內 AddAsync 一樣是使用 DB Model
public class Create : PageModel
{
private readonly IAccountService _accountService;
public Create(IAccountService accountService)
{
_accountService = accountService;
}
//建立需要的 Model
public class InputModel
{
[Display(Name = "帳號")]
[Required]
[StringLength(50)]
public string Name { get; set; }
[Display(Name = "密碼")]
[Required]
[StringLength(1000)]
public string Password { get; set; }
[Display(Name = "暱稱")]
[Required]
[StringLength(50)]
public string NickName { get; set; }
[Display(Name = "EMAIL")]
[Required]
[StringLength(300)]
public string Email { get; set; }
}
//指定前端可以使用 @Model.Input 取得資料
[BindProperty]
public InputModel Input { get; set; }
public void OnGet()
{
}
public async Task<IActionResult> OnPostAsync()
{
//Post 會跑來這,就是看方法名稱直接對應
if (ModelState.IsValid==false)
{
return Page();
}
var newData = new Data.Account()
{
Id = Guid.NewGuid()
, Name = Input.Name
, NickName = Input.NickName
, Password = Input.Password
, Email = Input.Email
, IsEnable = true
};
await _accountService.AddAsync(newData);
await _accountService.CommitAsync();
return RedirectToPage("./Index");
}
}
不要直接滑過,仔細看一下上方的 Code ,Razor Pages 因為有 Page Model 因此新增需要的欄位就直接在這頁建立,包含驗證與欄位資訊都在同一份檔案,再來看屬性的部分,InputModel 是這頁專屬,它的名稱 Input 也是這頁的這代表什麼?這表示我們不用再想命名了...可以所有的頁面都是這樣用,外部的 Model 資料夾也不再有一堆 Class 在那裡。
以前 MVC 框架有人反應拆太細了,大多數專案其實不需要那麼龐大的架構,現在有了更聚焦更輕量化的 Razor Pages,或許對於我們是一個不錯的解法,原本新增的部分沒有打算示範那麼多 MVC 的寫法,但一不小心就寫了一堆,所以編輯的部分就留到下一次吧。
回應討論