多年下來,寫程式發 Email 通知的需求做過 N 回,其中寄給客戶的通知為求美觀常需採用 HTML 格式,而客戶姓名、通知內容等要隨客戶動態改變,嚴格來說也是一種套表。過去我慣用一套自己發明的「特別註記+Replace」做法,例如:
var tmpl = "<span>[$Name$]</span> 您好,您的等侯順位為<span>[$SeqNo$]</span>";
var dict = new Dictionary<string, string>()
{
["Name"] = "Jeffrey",
["SeqNo"] = "007"
};
var res = System.Text.RegularExpressions.Regex.Replace(
tmpl, @"\[\$(?<n>.+?)\$\]", m =>
{
var n = m.Groups["n"].Value;
return dict.ContainsKey(n) ? dict[n] : "<" + n + ">";
});
Console.WriteLine(res);
Console.Read();
土砲做法雖然簡陋,不能 IF ELSE 也沒法跑迴圈,倒也淺顯易懂,就這麼一用十幾年 XD
最近專案又有類似需求打算重操舊業,轉念一想,一帖老方子從 VB6 寫到 C# 6 未免太不長進,該想想有沒有更好的方法。接著馬上有個念頭浮現腦海 - 寫了那麼多 ASP.NET MVC 見識過 CSHTML 的威力,既然信件內文也是 HTML,為什麼不用 Razor 來套版呢?
爬文很快找到順手的兵刃 – RazorEngine,一個允許在任何 .NET 專案(不必是 ASP.NET MVC)使用 Razor 的程式庫:
來個實例,假設我有個中獎通知函要動態改變中獎者姓名、頭銜、獎項內容與日期,若用 Razor 來寫會像這樣(MailTemplate.cshtml):
@model RazorMailTmpl.Models.MailData
<!DOCTYPEhtml>
<html>
<head>
<metacharset="utf-8"/>
<title>Razor Mail Template Demo</title>
<style>
li { color: #0000ff; }
.due { color: orangered; }
</style>
</head>
<body>
<p>親愛的 @Model.WinnerName @Model.Title,</p>
<p>感謝您參加部落格讀者2017年終摸彩,在此恭喜您獲得以下獎項:</p>
<ul>
@foreach (var prize in Model.Prizes)
{
<li>@prize</li>
}
</ul>
<p>
請在
<spanclass="due">@Model.DueDate.ToString("yyyy/MM/dd")</span>
前連絡謎之聲領取獎項。
</p>
<p>再次恭喜您幸運中獎!</p>
<p>Regards,<br/>黑暗執行緒部落格抽獎小組</p>
</body>
</html>
接著宣告一個 MailData 資料型別,這樣在編輯 cshtml 時才能享受強型別與 Inetllisense 提示:
using System;
namespace RazorMailTmpl.Models
{
publicclass MailData
{
publicstring WinnerName { get; set; }
publicstring Title { get; set; }
publicstring[] Prizes { get; set; }
public DateTime DueDate { get; set; }
}
}
要用 RazorEngine 套表很簡單,先建好 MailData 物件,使用 Engin.Razor.AddTemplate() 載入範本,引擎內建 Cache 機制,接著呼叫 Run 或 Compile 以 Cache Key 取出範本進行編譯運算,很快就能得到套表後的 HTML 字串結果:
using RazorEngine;
using RazorEngine.Templating;
using RazorMailTmpl.Models;
using System;
namespace RazorMailTmpl
{
class Program
{
staticvoid Main(string[] args)
{
var mailData = new MailData()
{
WinnerName = "Jeffrey",
DueDate = new DateTime(2018, 2, 14),
Title = "老司機",
Prizes = newstring[]
{
"32G USB 行動碟一支",
"Visual Studio 2017 紀念貼紙一組",
"法拉帝(Ferretti) 660 豪華遊艇(20米)一艘"
}
};
//將Template存入Cache以利重複使用
Engine.Razor.AddTemplate(
"MailBody", // Cache Key
System.IO.File.ReadAllText("MailTemplate.cshtml"));
//傳入Cache Key、Model物件型別、Model物件取得套表結果
var result =
Engine.Razor.RunCompile("MailBody", typeof(MailData), mailData);
//除了RunCompile,也可Compile一次,Run多次以提高效能
Engine.Razor.Compile("MailBody", typeof(MailData));
Engine.Razor.Run("MailBody", typeof(MailData), mailData);
System.IO.File.WriteAllText("Result.html", result);
}
}
}
薑!薑!薑!薑~ 完成。
官方文件的說明挺詳細,相信有 MVC cshtml 經驗的同學很快就能上手,祝大家套表愉快。