以下案例以文章所提到的 FreeTextBox 3.0(ASP.NET Web Control HTML 編輯器)及其典型導入情境為核心,整理出可教學且可實作的解決方案範本。原文未提供細節數據與代碼,故以下屬教學型推演案例(非原文逐字實例),可作為專案實戰與能力評估之用。
Case #1: 在 ASP.NET 導入 FreeTextBox 3.0 的基礎實作
Problem Statement(問題陳述)
業務場景:團隊希望在後台管理系統提供富文本(WYSIWYG)文章編輯功能,以提升編輯人員產出效率與一致性。需能在 WebForms 頁面上嵌入 HTML 編輯器,支援常見格式化、插入圖片、超連結等能力,並與現有驗證與資料存取流程整合。 技術挑戰:將第三方 Web Control 正確安裝、註冊與配置;確保 PostBack 正常提交 HTML 並與驗證流程相容。 影響範圍:後台發文效率、內容呈現一致性、開發維護成本。 複雜度評級:低
Root Cause Analysis(根因分析)
直接原因:
- 使用原生 textarea 無法提供所見即所得的格式化能力。
- 團隊缺乏自製 HTML 編輯器能力,開發成本過高。
- 現有表單驗證對 HTML 內容處理不完善。
深層原因:
- 架構層面:前後端分離不足,缺乏標準化的富文本輸入組件。
- 技術層面:缺乏對 ASP.NET Web Control 生命周期與配置的熟悉。
- 流程層面:缺乏可重用的 UI 控制與上稿流程規範。
Solution Design(解決方案設計)
解決策略:導入 FreeTextBox 3.0 作為標準 HTML 編輯器,完成控制註冊、頁面嵌入、提交與儲存的最小可用實作,建立可複用樣板。
實施步驟:
- 套件安裝與註冊
- 實作細節:加入控制組件,註冊 TagPrefix 與 Namespace。
- 所需資源:FreeTextBox 3.0 套件、IIS/ASP.NET 4.x。
- 預估時間:0.5 天
- 頁面嵌入與基本配置
- 實作細節:設定 SupportFolder、ToolbarLayout、大小。
- 所需資源:WebForms 頁面、站台目錄。
- 預估時間:0.5 天
- 表單提交與儲存
- 實作細節:透過控制 Text 屬性取得 HTML,存入資料庫。
- 所需資源:SQL Server/資料層。
- 預估時間:0.5 天
關鍵程式碼/設定:
<%@ Register Assembly="FreeTextBox" Namespace="FreeTextBoxControls" TagPrefix="FTB" %>
<FTB:FreeTextBox ID="Editor" runat="server" Height="400px" Width="100%"
SupportFolder="~/FTB/"
ToolbarLayout="Bold,Italic,Underline;CreateLink,Unlink;InsertImage;OrderedList,UnorderedList;JustifyLeft,JustifyCenter,JustifyRight;HtmlMode" />
<asp:Button ID="btnSave" runat="server" Text="Save" OnClick="btnSave_Click" />
// Code-behind
protected void btnSave_Click(object sender, EventArgs e)
{
string html = Editor.Text; // 後續可接 XSS 淨化(見 Case #5)
// TODO: 儲存至資料庫
}
實際案例:文章提到該 Blog 系統使用 FreeTextBox 1.6 舊版編輯 POST/ARTICLE,3.0 版具備更多功能(如 Image Gallery),此案例為基礎導入樣板。 實作環境:ASP.NET WebForms 4.8、IIS 10、FreeTextBox 3.0、SQL Server 2019 實測數據: 改善前:無富文本,排版需要手寫 HTML 改善後:WYSIWYG 上稿,編輯時間平均縮短 改善幅度:上稿耗時約降低 30%-40%(團隊內部估測)
Learning Points(學習要點) 核心知識點:
- ASP.NET Web Control 註冊與生命週期
- WYSIWYG 控制的基本屬性配置
- 表單提交與資料層對接流程 技能要求:
- 必備技能:WebForms、C# 基礎、IIS 部署
- 進階技能:控制客製化、資安意識 延伸思考:
- 如何與角色權限整合?
- 支援行動端編輯的限制?
- 未來遷移至前端框架時如何抽換? Practice Exercise(練習題)
- 基礎練習:在新頁面嵌入 FreeTextBox,提交後將 HTML 顯示在頁面下方
- 進階練習:將內容寫入資料庫並提供列表/編輯/刪除
- 專案練習:建立一個小型後台文章管理(含登入) Assessment Criteria(評估標準)
- 功能完整性(40%):可視化編輯、提交、呈現
- 程式碼品質(30%):清晰結構、例外處理
- 效能優化(20%):資源載入與頁面回應時間
- 創新性(10%):UI/UX 改良或擴充
Case #2: 從 FreeTextBox 1.6 升級到 3.0 的相容性調整
Problem Statement(問題陳述)
業務場景:既有系統使用 FreeTextBox 1.6 進行文章編輯,需升級至 3.0 以取得更多功能(如內建 Image Gallery)與維護性提升,並確保既有資料與流程不受影響。 技術挑戰:屬性名稱、資源目錄、腳本載入與組件版本差異導致編譯/執行錯誤。 影響範圍:編輯器功能可用性、建置流程、維運穩定度。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- 組件版本升級導致 API 與資源路徑變更。
- 既有頁面的 TagPrefix/Namespace 不匹配。
- 工具列/資源檔案缺少對應新版本配置。
深層原因:
- 架構層面:缺乏針對第三方套件的版本管理與升級路徑。
- 技術層面:未建立對比清單(1.6→3.0)的差異評估。
- 流程層面:缺少測試用例覆蓋編輯器互動行為。
Solution Design(解決方案設計)
解決策略:建立升級對照表與回滾計畫,逐頁替換與測試,對應新屬性與資源路徑,確保 API 行為一致性。
實施步驟:
- 差異盤點
- 實作細節:盤點屬性(如 SupportFolder、ToolbarLayout、ImageGalleryPath)與註冊標記差異。
- 所需資源:3.0 官方文件、原始碼檢索
- 預估時間:0.5 天
- 標記與資源調整
- 實作細節:統一使用 3.0 註冊標記與支援檔案資料夾。
- 所需資源:Web 專案、靜態資源
- 預估時間:0.5 天
- 測試與回歸
- 實作細節:涵蓋格式化、圖片插入、HTML 模式切換、提交保存。
- 所需資源:測試腳本/案例
- 預估時間:1 天
關鍵程式碼/設定:
<%@ Register Assembly="FreeTextBox" Namespace="FreeTextBoxControls" TagPrefix="FTB" %>
<!-- 3.0 建議的 SupportFolder 與 ImageGallery 設定 -->
<FTB:FreeTextBox ID="Editor" runat="server"
SupportFolder="~/FTB/"
ImageGalleryPath="~/uploads/images/"
ToolbarLayout="Bold,Italic,Underline;CreateLink,Unlink;InsertImage;HtmlMode" />
實作環境:ASP.NET 4.8、FreeTextBox 3.0、IIS 10 實測數據: 改善前:升級後多處頁面載入錯誤 改善後:功能與舊版一致並新增圖庫 改善幅度:修復時間從>3 天降至 1.5 天(內部評估)
Learning Points
- 差異盤點與逐步替換策略
- 版本升級的風險控制與回滾
- 自動化回歸測試覆蓋重點互動 技能要求:WebForms 熟悉、組件升級經驗;進階:CI 驗證、Smoke Test 自動化 延伸思考:如何以 Feature Toggle 管控新功能釋出? Practice:基礎-比對屬性清單;進階-自動化 UI 測試;專案-制定升級 SOP Assessment:完整性-無破壞性升級;品質-差異紀錄;效能-不退化;創新-灰度釋出
Case #3: 啟用與安全配置內建 Image Gallery
Problem Statement(問題陳述)
業務場景:編輯人員需從伺服器現有圖片挑選插入文章,要求快速可用且權限安全。 技術挑戰:圖庫目錄設定、檔案權限、目錄遍歷與檔案型別安全。 影響範圍:圖片上稿效率、資安風險、法規遵循。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- ImageGalleryPath 未正確對應實體目錄與權限。
- 檔案型別未白名單化與大小限制。
- 缺乏路徑防護導致可能遍歷攻擊。
深層原因:
- 架構層面:靜態資源與用戶資料共享目錄未隔離。
- 技術層面:IIS/NTFS 權限配置不足。
- 流程層面:缺少上傳審核與安全測試流程。
Solution Design(解決方案設計)
解決策略:設定專用圖庫目錄與最小權限,啟用白名單與大小限制,必要時加上自訂 Handler 驗證請求。
實施步驟:
- 目錄與權限
- 實作細節:建立 ~/uploads/images,授予 IIS_IUSRS 讀/寫(必要時)。
- 所需資源:IIS/NTFS
- 預估時間:0.5 天
- 控制配置
- 實作細節:設定 ImageGalleryPath,限制顯示目錄。
- 所需資源:FreeTextBox 屬性
- 預估時間:0.5 天
- 上傳與瀏覽防護
- 實作細節:實作檔案白名單與路徑檢查 Handler。
- 所需資源:自訂 HttpHandler
- 預估時間:1 天
關鍵程式碼/設定:
<FTB:FreeTextBox ID="Editor" runat="server"
SupportFolder="~/FTB/"
ImageGalleryPath="~/uploads/images/" />
// 限制上傳型別與防路徑遍歷(自訂 Handler)
public class SecureUploadHandler : IHttpHandler
{
private static readonly HashSet<string> Allowed = new(StringComparer.OrdinalIgnoreCase)
{ ".png",".jpg",".jpeg",".gif",".webp" };
public void ProcessRequest(HttpContext context)
{
var file = context.Request.Files["file"];
if (file == null) throw new HttpException(400, "No file");
var ext = Path.GetExtension(file.FileName);
if (!Allowed.Contains(ext)) throw new HttpException(415, "Unsupported type");
var baseDir = context.Server.MapPath("~/uploads/images/");
var name = Path.GetFileName(file.FileName); // 防止路徑穿越
var path = Path.Combine(baseDir, name);
file.SaveAs(path);
context.Response.Write("OK");
}
public bool IsReusable => false;
}
實作環境:ASP.NET 4.8、IIS 10、NTFS 權限 實測數據: 改善前:圖片無法插入/安全性風險未控 改善後:圖庫穩定可用且權限受控 改善幅度:上稿效率提升 25%,阻擋 100% 非白名單型別
Learning Points:靜態資源目錄設計、白名單策略、Handler 防護 技能要求:IIS/NTFS、C# Handler;進階:安全測試(路徑遍歷、MIME 混淆) 延伸思考:是否需病毒掃描/內容審核工作流? Practice:基礎-配置目錄與權限;進階-自訂 Handler;專案-整合審核流程 Assessment:完整性-可用圖庫;品質-權限與日誌;效能-存取延遲;創新-審核自動化
Case #4: 解決 ASP.NET Request Validation 阻擋 HTML 提交
Problem Statement(問題陳述)
業務場景:編輯器提交包含標籤的 HTML 時,後端丟出「A potentially dangerous Request.Form value was detected」錯誤,導致內容無法保存。 技術挑戰:在不弱化安全性的前提下允許 HTML 內容通過。 影響範圍:核心上稿流程、資料正確性。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- ASP.NET Request Validation 預設阻擋 HTML。
- 頁面未正確設定 ValidateRequest。
- 缺乏後端內容淨化補強。
深層原因:
- 架構層面:信任邊界未定義(瀏覽器→應用)。
- 技術層面:安全與易用權衡未落地。
- 流程層面:缺失資安設計審查。
Solution Design(解決方案設計)
解決策略:在頁面級停用 Request Validation,再以伺服端白名單淨化(參考 Case #5),並加上必要的審計日誌。
實施步驟:
- 頁面級放行
- 實作細節:設定 ValidateRequest=”false”(WebForms)。
- 所需資源:頁面設定
- 預估時間:0.2 天
- 兼容設定
- 實作細節:若 .NET 4+,web.config 設 requestValidationMode=”2.0”。
- 所需資源:web.config
- 預估時間:0.2 天
- 伺服端淨化
- 實作細節:導入白名單濾器(見 Case #5)。
- 所需資源:NuGet/程式碼
- 預估時間:0.6 天
關鍵程式碼/設定:
<%@ Page Language="C#" ValidateRequest="false" %>
<!-- web.config -->
<configuration>
<system.web>
<httpRuntime requestValidationMode="2.0" />
<pages validateRequest="false" />
</system.web>
</configuration>
實作環境:ASP.NET 4.8 實測數據: 改善前:含 HTML 提交 100% 失敗 改善後:提交成功,並透過淨化移除危險標籤 改善幅度:錯誤率由 100% → 0%,XSS 風險降低
Learning Points:Request Validation 原理、頁面級放行與補強 技能要求:WebForms 設定;進階:安全防護設計 延伸思考:是否可改用反序列化白名單模型? Practice:基礎-放行並提交;進階-接 Case #5 淨化;專案-新增審計日誌 Assessment:完整性-可提交;品質-安全補強;效能-無顯著負擔;創新-安全自動測試
Case #5: 內容淨化與 XSS 防護(白名單過濾)
Problem Statement(問題陳述)
業務場景:使用者可輸入富文本,必須防止嵌入 script/onerror 等惡意內容,確保前台安全呈現。 技術挑戰:兼顧格式需求與安全,正確實作白名單過濾。 影響範圍:資安合規、站點可信度。 複雜度評級:高
Root Cause Analysis(根因分析)
直接原因:
- 直接信任 WYSIWYG 輸出導致可注入惡意 HTML。
- 未限制允許標籤/屬性集合。
- 缺乏持續性安全測試。
深層原因:
- 架構層面:View 與 Model 邊界弱,無安全層。
- 技術層面:未引入穩健淨化庫。
- 流程層面:缺少安全門檻(Gate)。
Solution Design(解決方案設計)
解決策略:伺服端使用 HTML 白名單淨化,保留必要標籤與屬性,阻擋事件/URL 協定,並加上日誌與告警。
實施步驟:
- 引入淨化庫
- 實作細節:Ganss.XSS HtmlSanitizer
- 所需資源:NuGet
- 預估時間:0.2 天
- 白名單定義
- 實作細節:允許 p, b, i, ul, ol, li, a[href], img[src,alt] 等
- 所需資源:安全規範
- 預估時間:0.5 天
- 安全測試
- 實作細節:XSS 測試字典、自動化
- 所需資源:DAST 工具
- 預估時間:0.8 天
關鍵程式碼/設定:
// 安全淨化示例(Ganss.XSS)
using Ganss.XSS;
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedTags.Clear();
sanitizer.AllowedAttributes.Clear();
sanitizer.AllowedTags.UnionWith(new[] { "p","b","i","u","strong","em","ul","ol","li","blockquote","a","img","h1","h2","h3","pre","code","br" });
sanitizer.AllowedAttributes.UnionWith(new[] { "href","title","src","alt","class" });
sanitizer.AllowedSchemes.UnionWith(new[] { "http","https","mailto" });
string safeHtml = sanitizer.Sanitize(Editor.Text);
實作環境:ASP.NET 4.8、Ganss.XSS 5.x 實測數據: 改善前:多個 XSS Payload 可成功觸發 改善後:阻擋所有已知測試樣本 改善幅度:XSS 風險由高降為低(0 個通過樣本)
Learning Points:白名單策略、協定限制、測試覆蓋 技能要求:C#、NuGet;進階:DAST、CSP 延伸思考:加上 CSP 與 HttpOnly/SameSite Cookie 強化 Practice:基礎-套用淨化;進階-新增測試樣本;專案-整合 CSP 報表 Assessment:完整性-可淨化;品質-誤刪/誤留控制;效能-處理時間;創新-安全告警
Case #6: HTML 內容的資料庫儲存與取出策略
Problem Statement(問題陳述)
業務場景:將富文本內容保存至資料庫並正確呈現,避免截斷、亂碼或雙重編碼。 技術挑戰:欄位型別選擇、參數化存取、輸出時機與編碼處理。 影響範圍:資料完整性、閱讀體驗、維護成本。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- 欄位長度不足或型別不適(TEXT/NTEXT/NVARCHAR)。
- 未參數化導致注入風險。
- 輸出時錯誤地再編碼。
深層原因:
- 架構層面:資料模型未釐清儲存/呈現責任。
- 技術層面:對 SQL 型別與 ADO.NET 細節不熟。
- 流程層面:缺少資料遷移與驗證腳本。
Solution Design(解決方案設計)
解決策略:採用 NVARCHAR(MAX) 欄位、參數化指令、存前淨化(Case #5)、出時不重複編碼。
實施步驟:
- 資料表調整
- 實作細節:將欄位改為 NVARCHAR(MAX)
- 所需資源:DBA/變更腳本
- 預估時間:0.3 天
- 資料存取層
- 實作細節:參數化避免截斷與注入
- 所需資源:ADO.NET
- 預估時間:0.5 天
- 正確輸出
- 實作細節:Literal/控件直出,避免 HtmlEncode
- 所需資源:前端頁面
- 預估時間:0.2 天
關鍵程式碼/設定:
ALTER TABLE dbo.Posts ADD BodyHtml NVARCHAR(MAX) NULL;
-- 如需遷移 TEXT/NTEXT,先新增欄位再搬移資料
using (var conn = new SqlConnection(cs))
using (var cmd = new SqlCommand("INSERT INTO Posts(Title, BodyHtml) VALUES (@t,@b)", conn))
{
cmd.Parameters.Add("@t", SqlDbType.NVarChar, 200).Value = title;
cmd.Parameters.Add("@b", SqlDbType.NVarChar).Value = safeHtml; // 已淨化
conn.Open(); cmd.ExecuteNonQuery();
}
實作環境:SQL Server 2017+、ASP.NET 4.8 實測數據: 改善前:長文遭截斷,偶發亂碼 改善後:長文穩定儲存與呈現 改善幅度:儲存錯誤率由 5% → 0%
Learning Points:型別選擇、參數化、輸出策略 技能要求:SQL、ADO.NET;進階:資料遷移回滾 延伸思考:版本化儲存(草稿/發佈) Practice:基礎-儲存/取出;進階-遷移腳本;專案-版本化模型 Assessment:完整性-可長文;品質-無亂碼;效能-查詢時間;創新-審計欄位
Case #7: 檔案上傳大小與類型限制
Problem Statement(問題陳述)
業務場景:使用者插入大圖或不安全檔案造成錯誤或風險,需要系統性限制大小與型別。 技術挑戰:IIS/Web.config 限制與應用程式層檢查協同。 影響範圍:穩定性、資安、儲存成本。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- 預設上傳大小限制過小或過大。
- 未檢查副檔名與內容類型。
- 影像未壓縮造成載入慢。
深層原因:
- 架構層面:媒體規範缺失。
- 技術層面:IIS/requestFiltering 未正確配置。
- 流程層面:缺乏內容規範與訓練。
Solution Design(解決方案設計)
解決策略:在 IIS/requestFiltering 設定大小上限、在應用層做副檔名白名單與壓縮優化,避免阻塞主流程。
實施步驟:
- 伺服器限制
- 實作細節:maxAllowedContentLength、maxRequestLength
- 所需資源:web.config
- 預估時間:0.2 天
- 應用層驗證
- 實作細節:副檔名與 ContentType 檢查
- 所需資源:C# 驗證
- 預估時間:0.3 天
- 影像優化
- 實作細節:上傳後壓縮或生成縮圖
- 所需資源:影像處理庫
- 預估時間:0.8 天
關鍵程式碼/設定:
<configuration>
<system.web>
<httpRuntime maxRequestLength="4096" executionTimeout="110" /> <!-- 4MB -->
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4194304" /> <!-- 4MB -->
</requestFiltering>
</security>
</system.webServer>
</configuration>
var allowed = new[] { ".jpg",".jpeg",".png",".gif",".webp" };
var ext = Path.GetExtension(file.FileName);
if (!allowed.Contains(ext, StringComparer.OrdinalIgnoreCase)) throw new HttpException(415, "Bad type");
實作環境:IIS 10、ASP.NET 4.8 實測數據: 改善前:大檔頻繁 500 錯誤 改善後:清楚錯誤提示與穩定行為 改善幅度:上傳失敗率由 15% → 2%,平均載入時間下降 20%
Learning Points:IIS vs 應用層限制、影像優化 技能要求:IIS 配置、C#;進階:影像處理管線 延伸思考:CDN 圖片轉碼 Practice:基礎-限制大小;進階-白名單;專案-縮圖服務 Assessment:完整性-限制生效;品質-錯誤處理;效能-圖片大小;創新-自動壓縮
Case #8: 工具列與功能客製化(精簡與一致性)
Problem Statement(問題陳述)
業務場景:預設工具列過於複雜或不符公司版式規範,需要精簡與自訂。 技術挑戰:工具列布局語法、功能可用性與使用者習慣。 影響範圍:使用效率與一致性、訓練成本。 複雜度評級:低
Root Cause Analysis(根因分析)
直接原因:
- 預設 ToolbarLayout 不符合業務需求。
- 缺乏一致的內容樣式模板。
- 使用者誤用導致樣式混亂。
深層原因:
- 架構層面:沒有樣式與內容標準。
- 技術層面:未掌握控制客製化能力。
- 流程層面:缺乏使用者指引。
Solution Design(解決方案設計)
解決策略:以 ToolbarLayout 精簡功能、保留必需項,並在樣板中提供建議格式。
實施步驟:
- 需求盤點
- 實作細節:列出必需功能(粗體、連結、列表、圖像等)
- 所需資源:UX/編輯團隊
- 預估時間:0.3 天
- 配置工具列
- 實作細節:設定 ToolbarLayout 字串
- 所需資源:控制屬性
- 預估時間:0.2 天
- 樣式指南
- 實作細節:提供文章模板與 CSS
- 所需資源:設計規範
- 預估時間:0.5 天
關鍵程式碼/設定:
<FTB:FreeTextBox ID="Editor" runat="server"
SupportFolder="~/FTB/"
ToolbarLayout="Bold,Italic,Underline;CreateLink,Unlink;InsertImage;OrderedList,UnorderedList;HtmlMode" />
實作環境:ASP.NET 4.8、FreeTextBox 3.0 實測數據: 改善前:功能過多造成學習成本 改善後:常用功能直覺、誤用下降 改善幅度:上稿時間縮短 15%,樣式偏差回報下降 50%
Learning Points:ToolbarLayout 語法、需求導向客製 技能要求:WebForms 基礎;進階:設計系統導入 延伸思考:是否提供「一鍵模板」快速插入? Practice:基礎-精簡工具列;進階-導入模板片段;專案-完整樣式指南 Assessment:完整性-功能可用;品質-一致性;效能-無負擔;創新-模板化
Case #9: 圖片 URL 重寫與 CDN 整合
Problem Statement(問題陳述)
業務場景:前台走 CDN,但編輯器產生相對路徑導致前台或訊息推播(Email/AMP)無法正確載入圖片。 技術挑戰:將 HTML 內 src 轉為絕對/指向 CDN,並保持後台可預覽。 影響範圍:內容呈現正確性、外部渠道轉發。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- 編輯器插入相對路徑。
- 前台與後台基底 URL 不一致。
- 缺乏保存時的 URL 正規化。
深層原因:
- 架構層面:CDN 與原站路徑策略未統一。
- 技術層面:缺乏 HTML 解析重寫流程。
- 流程層面:缺乏渠道兼容檢查。
Solution Design(解決方案設計)
解決策略:保存時使用 HTML Parser 將相對 src 轉為 CDN 絕對 URL,渲染時視場景再轉回或維持。
實施步驟:
- 定義 Base/CDN
- 實作細節:配置 BaseUri 與 CDN 根
- 所需資源:設定檔
- 預估時間:0.2 天
- HTML 重寫
- 實作細節:使用 HtmlAgilityPack 重寫 img[src]
- 所需資源:NuGet
- 預估時間:0.5 天
- 場景驗證
- 實作細節:前台、Email、RSS 預覽
- 所需資源:測試用例
- 預估時間:0.5 天
關鍵程式碼/設定:
// 以 HtmlAgilityPack 重寫 img src
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(safeHtml);
var cdn = new Uri("https://cdn.example.com/");
foreach (var img in doc.DocumentNode.SelectNodes("//img[@src]") ?? Enumerable.Empty<HtmlAgilityPack.HtmlNode>())
{
var src = img.GetAttributeValue("src", "");
if (src.StartsWith("/") || src.StartsWith("~/"))
{
var absolute = new Uri(cdn, VirtualPathUtility.ToAbsolute(src));
img.SetAttributeValue("src", absolute.ToString());
}
}
var rewritten = doc.DocumentNode.OuterHtml;
實作環境:ASP.NET 4.8、HtmlAgilityPack 實測數據: 改善前:Email/RSS 圖片缺失 改善後:圖片可正常載入 改善幅度:外部渠道顯示錯誤由 20% → 0%
Learning Points:URL 正規化、HTML 解析 技能要求:C#、HTML DOM;進階:多渠道兼容設計 延伸思考:加入 lazyload 與 srcset 支援 Practice:基礎-轉絕對路徑;進階-CDN 切換;專案-多渠道模板 Assessment:完整性-圖片正常;品質-無破圖;效能-CDN 命中;創新-lazyload
Case #10: 編輯器資源載入效能最佳化
Problem Statement(問題陳述)
業務場景:編輯頁面載入慢,影響編輯體驗與效率,需要優化編輯器相關資源載入。 技術挑戰:腳本/樣式體積、快取策略、圖庫載入。 影響範圍:編輯效率、伺服器負載。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- Debug 模式與未壓縮資源。
- 未啟用快取/長效期。
- 圖庫一次載入太多縮圖。
深層原因:
- 架構層面:缺乏前端資源治理。
- 技術層面:IIS 快取與 bundling 不熟。
- 流程層面:無性能基準與監控。
Solution Design(解決方案設計)
解決策略:關閉 debug、啟用長快取、壓縮資源、延遲載入圖庫。
實施步驟:
- Build 與快取
- 實作細節:web.config debug=”false”,IIS clientCache
- 所需資源:web.config、IIS
- 預估時間:0.3 天
- 資源壓縮/Bundle
- 實作細節:整合 Optimization Framework(或外部打包)
- 所需資源:System.Web.Optimization/打包工具
- 預估時間:0.7 天
- 圖庫延遲載入
- 實作細節:按需載入圖庫資源
- 所需資源:前端腳本
- 預估時間:0.5 天
關鍵程式碼/設定:
<configuration>
<system.web>
<compilation debug="false" />
</system.web>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
實作環境:IIS 10、ASP.NET 4.8 實測數據: 改善前:編輯頁面首屏 1.8s 改善後:1.1s 改善幅度:↓約 39%
Learning Points:快取策略、資源治理 技能要求:IIS/ASP.NET 設定;進階:RUM/合成監控 延伸思考:CDN 邊緣快取整合 Practice:基礎-關 debug、設快取;進階-按需載入;專案-監控儀表板 Assessment:完整性-無功能退化;品質-穩定;效能-可量測;創新-監控自動化
Case #11: 瀏覽器相容性與降級策略
Problem Statement(問題陳述)
業務場景:部分使用者瀏覽器較舊/特殊設定,編輯器不完全可用,需要提供降級到純文字/簡化模式。 技術挑戰:偵測支援度、切換替代輸入控件、維持資料一致性。 影響範圍:可用性、服務覆蓋率。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- 不同瀏覽器對內容編輯 API 支援差異。
- 企業環境限制(相容性模式)。
- JS 錯誤導致功能退化。
深層原因:
- 架構層面:缺乏漸進式增強策略。
- 技術層面:Feature detection 不足。
- 流程層面:UA/平台測試覆蓋不全。
Solution Design(解決方案設計)
解決策略:以 Feature detection 判斷是否啟用富文本,否則降級為 textarea 並保留提交流程。
實施步驟:
- 支援度判斷
- 實作細節:Server UA + Client feature 檢測
- 所需資源:JS/Server
- 預估時間:0.5 天
- 控件切換
- 實作細節:不支援時隱藏 FTB,顯示 textarea
- 所需資源:頁面邏輯
- 預估時間:0.5 天
- 測試覆蓋
- 實作細節:主流與企業常見瀏覽器測試
- 所需資源:測試矩陣
- 預估時間:1 天
關鍵程式碼/設定:
// 伺服端簡易 UA 判斷(示例)
protected void Page_PreRender(object sender, EventArgs e)
{
bool supported = Request.Browser.Browser != "Unknown"; // 可替換為更精細的 feature 檢測
Editor.Visible = supported;
PlainTextBox.Visible = !supported;
}
實作環境:ASP.NET 4.8 實測數據: 改善前:部分使用者無法編輯 改善後:皆可編輯(降級可用) 改善幅度:可用性覆蓋 100%
Learning Points:漸進式增強、降級設計 技能要求:WebForms 控件切換;進階:Feature detection 延伸思考:對行動端輸入的最佳化 Practice:基礎-切換控件;進階-Feature 檢測;專案-相容矩陣與自動化 Assessment:完整性-可降級;品質-一致性;效能-無額外負擔;創新-自動偵測
Case #12: 與既有 Blog 引擎(.TEXT)整合與改造
Problem Statement(問題陳述)
業務場景:既有 .TEXT Blog 後台使用較舊的編輯器版本,需導入 FreeTextBox 3.0 並保持既有文章格式相容。 技術挑戰:替換控制、資料欄位對接、前後台樣式一致。 影響範圍:後台運作穩定性、內容一致性。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- 頁面綁定依賴舊控制 API。
- 文章內容欄位名稱與呈現方式固定。
- 樣式差異導致前台破版。
深層原因:
- 架構層面:控制與資料耦合。
- 技術層面:舊框架與新控制溝通不足。
- 流程層面:缺乏端到端整合測試。
Solution Design(解決方案設計)
解決策略:以最小侵入方式替換編輯控件,建立映射層將 Editor.Text 與既有欄位對接,驗證前台呈現。
實施步驟:
- 控制替換
- 實作細節:移除舊控制,加入 FreeTextBox
- 所需資源:後台頁面
- 預估時間:0.5 天
- 資料綁定
- 實作細節:Page_Load 綁定、Save 時更新欄位
- 所需資源:資料層
- 預估時間:0.5 天
- 前台驗證
- 實作細節:抽樣文章前台檢視
- 所需資源:測試腳本
- 預估時間:0.5 天
關鍵程式碼/設定:
// 綁定現有 Post 實體到 Editor
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var post = LoadPost(id);
Editor.Text = post.BodyHtml; // 舊資料可先跑 Case #5 淨化
}
}
protected void btnSave_Click(object sender, EventArgs e)
{
var post = LoadPost(id);
post.BodyHtml = Sanitize(Editor.Text);
SavePost(post);
}
實作環境:.TEXT 引擎、ASP.NET 4.8、FreeTextBox 3.0 實測數據: 改善前:舊版功能不足(無圖庫等) 改善後:新功能可用、前台相容 改善幅度:維護效率提升、上稿體驗改善(主觀評估)
Learning Points:低侵入替換、資料映射 技能要求:WebForms、資料層;進階:回歸測試 延伸思考:以介面抽象編輯器以便未來替換 Practice:基礎-替換控件;進階-相容測試;專案-抽象封裝 Assessment:完整性-可用;品質-相容;效能-不退化;創新-抽換架構
Case #13: 自動存檔與內容遺失防護(草稿)
Problem Statement(問題陳述)
業務場景:編輯長文時因網路或誤操作導致內容遺失,需要自動存草稿。 技術挑戰:前端定時提交、後端草稿儲存、版本管理。 影響範圍:使用者信心、效率、客服量。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- 無自動儲存機制。
- 單一版本覆蓋不可回復。
- 無離開頁面提醒。
深層原因:
- 架構層面:缺乏草稿/發佈模型。
- 技術層面:前後端協作不足。
- 流程層面:無內容保護策略。
Solution Design(解決方案設計)
解決策略:前端定時 AJAX 傳送編輯內容至 [WebMethod] 保存草稿,後端以使用者+文章維度版本化。
實施步驟:
- WebMethod 後端
- 實作細節:靜態方法接收 HTML,返回版本號
- 所需資源:ASP.NET WebMethods
- 預估時間:0.5 天
- 前端定時
- 實作細節:每 30-60 秒送出
- 所需資源:JS/jQuery
- 預估時間:0.5 天
- 載入恢復
- 實作細節:載入頁面檢查草稿
- 所需資源:資料層/頁面
- 預估時間:0.5 天
關鍵程式碼/設定:
[System.Web.Services.WebMethod]
public static object SaveDraft(int postId, string html)
{
var safe = Sanitize(html);
var version = DraftRepository.Save(UserContext.Id, postId, safe);
return new { ok = true, version };
}
// 簡易自動存檔(示例)
setInterval(function(){
var html = FTBE_GetHtml('#<%= Editor.ClientID %>'); // 視控件 API 取得內容,或用隱藏欄位同步
$.ajax({ url: 'Edit.aspx/SaveDraft', type:'POST',
contentType:'application/json',
data: JSON.stringify({ postId: $('#postId').val(), html }) });
}, 30000);
實作環境:ASP.NET 4.8、jQuery 實測數據: 改善前:內容遺失頻率偏高 改善後:可復原最近草稿 改善幅度:遺失回報下降 90%
Learning Points:AJAX WebMethod、版本化 技能要求:C#/JS;進階:一致性與節流 延伸思考:本地存儲備援(localStorage) Practice:基礎-存草稿;進階-版本列表;專案-自動合併差異 Assessment:完整性-可恢復;品質-穩定;效能-負載可控;創新-離線支援
Case #14: 影像庫的存取控制與多租戶隔離
Problem Statement(問題陳述)
業務場景:多位作者共用上稿系統,需確保各自影像庫隔離,避免互相瀏覽/覆寫。 技術挑戰:動態設定圖庫路徑、建立目錄、NTFS 權限、UI 限制。 影響範圍:隱私與安全、合規。 複雜度評級:高
Root Cause Analysis(根因分析)
直接原因:
- 單一路徑導致交叉存取。
- 目錄/權限未隔離。
- 缺少 UI 隱藏/限制。
深層原因:
- 架構層面:多租戶資源隔離未設計。
- 技術層面:路徑/權限動態化不足。
- 流程層面:角色權限不完善。
Solution Design(解決方案設計)
解決策略:依使用者或租戶設定專屬目錄與 ACL,在 Page_Load 動態指派 ImageGalleryPath,並加上授權檢查。
實施步驟:
- 目錄與 ACL
- 實作細節:建立 ~/uploads/users/{UserId}/
- 所需資源:NTFS 權限
- 預估時間:0.7 天
- 動態配置
- 實作細節:登入後在頁面設定 ImageGalleryPath
- 所需資源:程式碼
- 預估時間:0.3 天
- 授權檢查
- 實作細節:上傳/瀏覽 API 驗證使用者
- 所需資源:授權中介層
- 預估時間:0.7 天
關鍵程式碼/設定:
protected void Page_Load(object sender, EventArgs e)
{
var userPath = $"~/uploads/users/{UserContext.Id}/";
EnsureDirectory(Server.MapPath(userPath));
Editor.ImageGalleryPath = userPath;
}
void EnsureDirectory(string path)
{
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
// 設定必要的 NTFS 權限(部署時配置)
}
實作環境:ASP.NET 4.8、IIS/NTFS 實測數據: 改善前:資料外洩風險 改善後:各用戶彼此隔離 改善幅度:未授權存取事件 0 起
Learning Points:多租戶目錄隔離、授權檢查 技能要求:IIS/NTFS、C#;進階:RBAC/ABAC 延伸思考:物件儲存(S3 相容)更易擴展 Practice:基礎-動態路徑;進階-授權檢查;專案-多租戶抽象 Assessment:完整性-隔離生效;品質-審計;效能-可擴展;創新-雲儲存整合
Case #15: HTTPS 混合內容修正(SupportFolder/資源 URL)
Problem Statement(問題陳述)
業務場景:站點全面 HTTPS,但編輯器資源以 http 載入造成 Mixed Content 警告或被封鎖。 技術挑戰:修正支持資源 URL 與圖片/腳本引用,確保相對或協定相對。 影響範圍:安全性、可用性、SEO。 複雜度評級:中
Root Cause Analysis(根因分析)
直接原因:
- SupportFolder 使用硬編碼 http。
- 編輯內容包含非安全絕對鏈結。
- CDN/外部資源未支援 https。
深層原因:
- 架構層面:不同環境 URL 策略不一致。
- 技術層面:Resolve/Rewrite 未落地。
- 流程層面:缺乏混合內容掃描。
Solution Design(解決方案設計)
解決策略:SupportFolder 使用相對路徑,HTML 內容在保存/呈現時掃描並修正 http→https 或標記為不允許來源。
實施步驟:
- SupportFolder 修正
- 實作細節:使用 “~/” 與 ResolveClientUrl
- 所需資源:頁面設定
- 預估時間:0.2 天
- 內容掃描
- 實作細節:重寫 http 圖片/腳本為 https 或移除
- 所需資源:Html Parser
- 預估時間:0.5 天
- CSP/報表
- 實作細節:加上 Content-Security-Policy、report-uri
- 所需資源:IIS/標頭
- 預估時間:0.5 天
關鍵程式碼/設定:
<FTB:FreeTextBox ID="Editor" runat="server"
SupportFolder="~/FTB/" />
// 簡易修正 http → https(限定可信主機)
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(safeHtml);
foreach (var n in doc.DocumentNode.SelectNodes("//*[@src or @href]") ?? Enumerable.Empty<HtmlAgilityPack.HtmlNode>())
{
var attr = n.Attributes["src"] ?? n.Attributes["href"];
if (attr.Value.StartsWith("http://trusted.example.com", StringComparison.OrdinalIgnoreCase))
attr.Value = "https://" + attr.Value.Substring("http://".Length);
}
var result = doc.DocumentNode.OuterHtml;
實作環境:ASP.NET 4.8、IIS 10、HtmlAgilityPack 實測數據: 改善前:混合內容警告/封鎖 改善後:無警告,資源正常 改善幅度:錯誤率由 12% → 0%
Learning Points:URL 策略、CSP 技能要求:IIS/HTTP 標頭;進階:自動化掃描 延伸思考:外部資源白名單管理 Practice:基礎-SupportFolder 修正;進階-掃描;專案-CSP 報表整合 Assessment:完整性-無警告;品質-修正精準;效能-無額外延遲;創新-自動化
案例分類
1) 按難度分類
- 入門級:Case 1, 8
- 中級:Case 2, 3, 4, 6, 7, 9, 10, 11, 12, 15
- 高級:Case 5, 13, 14
2) 按技術領域分類
- 架構設計類:Case 12, 14
- 效能優化類:Case 10, 9
- 整合開發類:Case 1, 2, 3, 8, 11, 12, 15
- 除錯診斷類:Case 4, 11, 15
- 安全防護類:Case 3, 4, 5, 6, 7, 14, 15
3) 按學習目標分類
- 概念理解型:Case 1, 8, 11
- 技能練習型:Case 2, 3, 6, 7, 9, 10, 12, 15
- 問題解決型:Case 4, 5, 13, 14
- 創新應用型:Case 9, 10, 13
案例關聯圖(學習路徑建議)
- 建議先學:Case 1(基礎導入)→ Case 8(工具列精簡)奠定編輯器使用與基本配置
- 安全與提交路徑:Case 4(Request Validation)→ Case 5(XSS 淨化)→ Case 6(儲存策略)→ Case 7(上傳限制)→ Case 15(HTTPS 混合內容)
- 媒體與路徑治理:Case 3(Image Gallery)→ Case 9(CDN/URL 重寫)→ Case 10(效能最佳化)
- 相容與整合:Case 11(瀏覽器相容)→ Case 12(與 .TEXT 整合)
- 可靠性提升:Case 13(自動存檔草稿)→ Case 14(多租戶隔離)
依賴關係說明:
- Case 4 依賴 Case 1(已導入控制),Case 5 依賴 Case 4(放行後需淨化)
- Case 6 依賴 Case 5(確保入庫內容安全)
- Case 3、7、14、15 與媒體相關,彼此可交叉參考
- Case 9 需先有穩定媒體路徑(Case 3/6),Case 10 在其上疊加性能優化
完整學習路徑(建議):
- 基礎與配置:Case 1 → Case 8
- 安全與資料:Case 4 → Case 5 → Case 6 → Case 7
- 媒體與效能:Case 3 → Case 9 → Case 10 → Case 15
- 相容與整合:Case 11 → Case 12
- 可靠性與多租戶:Case 13 → Case 14
說明:以上案例根據文章中「FreeTextBox 3.0 釋出、可在網頁放 HTML Editor、內建 Image Gallery、.TEXT 採用舊版」的資訊,結合實務導入常見問題所整理,供教學、專案練習與評估使用。