淺談 ASP.NET Core Tag Helper (標籤協助程式)
4 |
學習新的開發寫法要投入時間,離開習慣的事物令人不安,因此轉移新版本或新平台過程總存在著無形阻力。此時常需要靠新版的某個迷人特性,才能讓你產生動力咬牙跨越圍籬。
像是 Interpolated Strings 字串插值,便是讓我積極改用 C# 6.0 的關鍵。至於 ASP.NET Core,MVC View 的 Razor 寫法與 ASP.NET MVC 5 差異不大(延伸閱讀:ASP.NET 簡史),但有個好物一直吸引我的目光 - Tag Helper (標籤協助程式)。
之前談 .js/.css 或圖檔 Cache 問題時有介紹過 Tag Helper,在 <script> 加上 app-append-version 自動產生 ?v=dLGP40S... 參數,當檔案內容修改 v 參數會自動改變,確保不會讀到舊版 Cache。這種在標準 HTML 標籤加上額外 Attribute 整合伺服端功能的概念,既能相容前端開發工具與習慣,又能結合後端 C# 邏輯,深得我心。
這篇文章就以大家熟悉的 MVC 5 欄位編輯網頁設計為例,介紹改用 Tag Helper 的新寫法。
直接借用 ASP.NET MVC 3 豬走路範例 (2)的 PlayerModel 資料型別,建立編輯玩家資料的 ASP.NET MVC 網頁。DemoController.cs 很簡單,Index Action 在 HttpGet 時純粹回傳 View,HttPost 時由前端接收 PlayerModel 型別,為示範 ValidationSummary 訊息呈現,故意用 ModelState.AddModelError() 加入錯誤:
using AspNetCore.Models;
using Microsoft.AspNetCore.Mvc;
namespace AspNetCore.Controllers
{
public class DemoController : Controller
{
[HttpGet]
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult Index(PlayerModel player)
{
//加入不隸屬特定屬性的錯誤,顯示於ValidationSummary
ModelState.AddModelError(
string.Empty, "Test Error Message");
return View();
}
}
}
Views/Demo/Index.cshtml 長這樣:
@model AspNetCore.Models.PlayerModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>TagHelper Demo</title>
</head>
<body>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>PlayerModel</legend>
<dl>
<dt>
@Html.LabelFor(m => m.Name)
</dt>
<dd>
@Html.EditorFor(m => m.Name)
@Html.ValidationMessageFor(m => m.Name)
</dd>
<dt>
@Html.LabelFor(m => m.Score)
</dt>
<dd>
@Html.EditorFor(m => m.Score)
@Html.ValidationMessageFor(m => m.Score)
</dd>
</dl>
<p>
<button>Create</button>
</p>
</fieldset>
}
</body>
</html>
網頁效果如下:
看起來是蠻簡潔的,但對有前端開發經驗的人來說,雖然知道 @Html.LabelFor(m => m.Name) 在執行階段會轉成 HTML 標籤,LableFor() 方法也有 IDictionary<String,Object> htmlAttributes 參數 可加入 class、onclick 等配合前端設計的 Attribute,但永遠比不上直接寫 <label> 直覺。
為了提供更好的前端開發體驗,ASP.NET Core 加入了一些表單與輸入欄位用的 Tag Helper,允許開發者直接寫 HTML 標籤再透過 Tag Helper 由 Model 自動取得屬性顯示名稱、檢核規則設定,實現與 LabelFor()、EditorFor()、ValidationFor() 相似的效果,而開發者又能保有對 HTML 元素的完整掌控,兩全其美。
改用 Tag Helper 後欄位輸入 View 寫法如下:
@model AspNetCore.Models.PlayerModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>TagHelper Demo</title>
</head>
<body>
<form asp-controller="Demo" asp-action="Index" method="post">
<div asp-validation-summary="ModelOnly"></div>
<fieldset>
<legend>PlayerModel</legend>
<dl>
<dt>
<label asp-for="Name"></label>
</dt>
<dd>
<input asp-for="Name" />
<span asp-validation-for="Name"></span>
</dd>
<dt>
<label asp-for="Score"></label>
</dt>
<dd>
<input asp-for="Score" />
<span asp-validation-for="Score"></span>
</dd>
</dl>
<p>
<button>Create</button>
</p>
</fieldset>
</form>
</body>
</html>
值得一提的是,Visual Studio 2019 認得這些 Tag Helper,一樣有 Intellisense,例如 asp-for 要輸入屬性名稱時便會自動列出 Model 的所有屬性,體驗不錯。
比較 HtmlHelper 版本(左)與 Tag Helper 版本(右):
HTML 前端開發經驗較少的同學可能仍會偏好 HtmlHelper,可以少碰一些 HTML 標籤;但如果你熟悉前端開發或想完整控制 HTML 元素,絕對會愛上 Tag Helper。
兵器百百種,大家各取所好,用得順手最重要!
Introduction of ASP.NET Core's tag helpers for form.
Comments
# by Eagle
黑大不考慮前後端分離,前端改用Angular框架或是其他框架?
# by Jeffrey
to Eagle, 我寫過一陣子 SPA,但近年心得是 cshtml + 前端框架(我選了 Vue.js) MVVM + AJAX 與後端溝通的寫法最簡便快速。
# by Will
>> Visual Studio 2019 認得這些 Tag Helper,一樣有 Intellisense 想請教一下 Visual Studio Code 是不是就不支援 Intellisense
# by Jeffrey
to Will, VSCode 的功能來自各式各樣的外掛套件,基本的、常用的幾乎都有:https://marketplace.visualstudio.com/items?itemName=schneiderpat.aspnet-helper