ASP.NET MVC 早期面臨開發者從 WebForms 控制項拖拉開發轉向手寫 HTML 的陣痛。但 MVC 提供的 HtmlHelper 機制,將伺服器端邏輯封裝為可複用的擴展方法,實現「關注點分離」同時保持開發效率。本文深入剖析 HtmlHelper 架構、ActionLink 運作原理,以及如何撰寫自訂擴展方法。
HtmlHelper 類別封裝了 ViewContext、IViewDataContainer、RouteCollection 等上下文資訊,本身非靜態類別,但提供大量靜態擴展方法。IntelliSense 中可見三類成員:
Encode()、AntiForgeryToken(),直接定義於 HtmlHelper 類別。ActionLink()、TextBox()、BeginForm(),定義於 System.Web.Mvc.Html 命名空間的靜態類別 LinkExtensions、InputExtensions、FormExtensions 中。EditorFor()、DisplayFor() 等,支援 DataAnnotations 與模板系統。
ActionLink 根據路由表動態產生錨點標籤 <a href="...">,支援多種多載:
// 基本用法
@Html.ActionLink("連結文字", "ActionName", "ControllerName")
// 帶路由值
@Html.ActionLink("編輯", "Edit", new { id = Model.Id })
// 指定 HTML 屬性
@Html.ActionLink("刪除", "Delete", new { id = 1 }, new { @class = "btn-danger", onclick = "return confirm('確定?')" })
內部透過 UrlHelper.GenerateUrl 解析路由,確保 URL 與路由表一致,避免硬式編碼 URL 字串。
擴展方法模式讓開發者能輕鬆注入功能。範例:建立 Label 輔助方法:
using System.Web.Mvc;
namespace MyProject.HtmlHelpers
{
public static class CustomExtensions
{
public static MvcHtmlString Label(this HtmlHelper helper, string name, string value)
{
var label = new TagBuilder("label");
label.Attributes.Add("for", name);
label.SetInnerText(value);
label.TagRenderMode = TagRenderMode.Normal;
return MvcHtmlString.Create(label.ToString() + "<br />");
}
}
}
在 View 中引用命名空間後即可使用:
@using MyProject.HtmlHelpers
@Html.Label("username", "使用者名稱")
參考社區知名專案(如 MvcContrib、JQueryHelper),可封裝常用 jQuery UI 元件:
public static MvcHtmlString DatePicker(this HtmlHelper helper, string name, DateTime? value)
{
var input = helper.TextBox(name, value.HasValue ? value.Value.ToString("yyyy/MM/dd") : "", new { @class = "datepicker" });
var script = "$(function(){ $('.datepicker').datepicker({ dateFormat: 'yy/mm/dd' }); });";
return MvcHtmlString.Create(input.ToHtmlString() + "<script>" + script + "</script>");
}
MyProject.HtmlHelpers),於 Views/Web.config 的 <namespaces> 註冊,全專案可用。MvcHtmlString 避免 HTML 編碼雙重轉義。TagBuilder 建構標籤,確保屬性正確編碼。HtmlHelper 的擴展機制展現了 MVC 框架的彈性:核心輕量、功能外掛。掌握此機制,能讓團隊建立專屬的 UI 元件庫,統一風格、提升開發速度,並為未來遷移至 ASP.NET Core Tag Helpers 奠基。