TagHelper如何讀取無編碼的HTML
- 2024-01-12
- 2507
- 0
當您在自訂 TagHelper 並使用 GetChildContentAsync()
方法來讀取標籤內容時,這是一個常見的應用場景。然而,如果內容中包含特殊符號,可能會遇到問題。因為安全考量,GetChildContentAsync()
方法預設讀取的 HTML 內容是經過編碼的。我曾花費許多時間嘗試將編碼後的文字還原,但始終無法找到解決方法。最終,我意識到我一開始的方向就錯了,因此特別撰寫這篇文章來記錄這次的學習經歷。
情境說明
在我的Blog後台中「參考資料」的設計是設計成一個TextArea,我只需要利用瀏覽器的Copy link as Markdown功能就可以快速的貼上多條的參考連結,每一個連結使用斷行來分隔。
傳到資料庫的內容就會是
[SkillTree](https://skilltree.my)\r\n[twMVC](https://mvc.tw)
前台顯示的時候利用自訂的TagHelper轉換成HTML語法的連結
<markdown-to-html-link>@Model.Source.RefUrl</markdown-to-html-link>
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "ul";
var content = await output.GetChildContentAsync();
var array = content.GetContent().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
...
}
在上面的部分可以看到我使用了Environment.NewLine
來作為分割字串,但當我升級到.NET7以後這段Code就壞了,因為預設編碼的問題,所以後端讀到的文字長這樣
問題來源
其中的/r/n
被編碼為

所以切割字串失敗導致後方一連串的非預期行為。這時候我的思緒就認為既然你預設編碼(HTML Encoder)了,那我就反編碼(HTML Decoder)就好,於是我找了一堆討論串和文章(以下是從瀏覽器歷史紀錄撈出來的,還有很多沒列出)
- TagHelperOutput.GetChildContentAsync Method (Microsoft.AspNetCore.Razor.TagHelpers) | Microsoft Learn
- HtmlEncoder Class (System.Text.Encodings.Web) | Microsoft Learn
- Complete list of ASCII Key Codes (codetable.net)
- ASP.NET Core View 中文變 & # x4E2D; & # x6587;-黑暗執行緒 (darkthread.net)
- .NET Core .cshtml 及 JSON 之 UnicodeRange 編碼範圍設定-黑暗執行緒 (darkthread.net)
解決方式
其中我在微軟官方文件有看到GetChildContentAsync()
是可以傳參數的,所以我一直在測試要傳哪種HTML Encoder才能達到我的期望,經歷了一番嘗試,並沒有什麼突破性的發展,突然靈機一動,利用 TagHelper 把Markdown轉HTML我絕對不會是第一個,而Markdown一定有分行符號,所以我轉成這方向去解,找到了這篇文章 Creating an ASP.NET Core Markdown TagHelper and Parser - Rick Strahl's Web Log (west-wind.com) 文章中我注意到了NullHtmlEncoder.Default
這個設定,我在苦苦尋找哪個Encoder可以用,卻沒想到有一個NullHtmlEncoder😅,立即修改程式碼如下
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "ul";
var content = await output.GetChildContentAsync(NullHtmlEncoder.Default);
var array = content.GetContent(NullHtmlEncoder.Default).Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
...
}
果然是拿到了未處理的HTML
其實這問題根本不是問題,如果一開始我沒有想偏直接往「不要編碼」的路走,根本不會繞那麼大一圈,但這一圈也不是白繞的,查資料的過程對於網頁編碼有了更多的認識,不見得是壞事,順便一題,查資料的過程大量使用 Microsoft Edge 內建的 Copilot 真的是很方便。
回應討論