TagHelper 是我喜愛的 ASP.NET Core 新功能之一 (延伸閱讀:淺談 ASP.NET Core Tag Helper (標籤協助程式)),在標準 HTML 元素加上 asp-for、asp-append-version 即能獲得額外功能,<input asp-for="Name"& > 遠比 MVC 5 時代用 HtmlHelper 寫 Html.LabelFor(m => m.Name) 簡潔易讀許多。除了為既有 HTML 元素添加功能,Tag Helper 還有一個我很想嘗試的應用方式 - 自訂 HTML 標籤。

這篇就來練習自製一個可輕鬆在網頁顯示 QRCode 的 Tag Helper。

關於自製 Tag Helper 的方法,微軟的這篇教學寫得頗詳細,這裡不多贅述,僅說說我遇到的小眉角。

先看成品:

Index.cshtml 原始碼如下,很簡潔吧!

@addTagHelper *,DemoWeb
@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <div>黑暗執行緒</div>
    <page-qr-code url="https://blog.darkthread.net"></page-qr-code>
    <div>本網頁</div>
    <page-qr-code size="8"></page-qr-code>
</div>

page-qr-code Tag Helper 有兩個參數 url 及 size。url 可指定 QR Code 要包含的網址或文字,不指定時則取目前瀏覽頁面的 URL;size 為顯示大小,若不指定,預設為 5。

PageQRCodeTagHelper 程式很短,在 Process() 中用 QRCoder 將 URL 轉為 QR Code PNG 圖檔 byte[],以 Data URI 格式指定為 img src,30 行搞定。

using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.Http.Extensions;

namespace DemoWeb.Models
{
    [HtmlTargetElement("page-qr-code")]
    public class PageQRCodeTagHelper : TagHelper
    {
        public int Size { get; set; } = 5;
        public string Url { get; set; }
        [ViewContext]
        [HtmlAttributeNotBound]
        public ViewContext ViewContext { get; set; }
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = "img";
            var url = string.IsNullOrEmpty(Url) ? ViewContext.HttpContext.Request.GetEncodedUrl() : Url;
            var qrCodeGen = new QRCoder.QRCodeGenerator();
            var data = qrCodeGen.CreateQrCode(System.Text.Encoding.UTF8.GetBytes(url), QRCoder.QRCodeGenerator.ECCLevel.Q);
            var img = new QRCoder.PngByteQRCode(data).GetGraphic(Size);
            var dataUri = $"data:image/png;base64,{Convert.ToBase64String(img)}";
            output.Attributes.Add("src", dataUri);
            output.Attributes.Add("alt", url);
        }
    }
}

過程挺順利,依直覺寫完就成功了,只有抓取目前 URL 時花了一點時間。

Tag Helper 不像 MVC Controller 可透過 HttpContext.Request 取得目前網址,要靠一個特殊的 ViewContextAttibute 取得 ViewContext 物件,作法是宣告以下屬性:

[ViewContext]
[HtmlAttributeNotBound]
public ViewContext ViewContext { get; set; }

Process() 便可透過 ViewContext.HttpContext.Request 取得 URL、登入帳號、來源 IP 等請求相關資訊。另外,ASP.NET Core 的 HttpRequest 不再有 UrlRawUrl 屬性,要改用 GetEncodedUrl()) 或 GetDisplayUrl() 擴充方法(記得 using Microsoft.AspNetCore.Http.Extensions)。

練習完畢。

A simple tag helper to insert QR code for specify url or current url.


Comments

Be the first to post a comment

Post a comment