[英]Razor View Page as Email Template
我從 Razor 語法設計了一個電子郵件模板。 當我使用 C# 代碼和 SMTP 協議將此模板作為電子郵件發送時,我得到裸露的 Razor 和 HTML 標記作為電子郵件正文。 這種方法我錯了嗎? Razor 頁面是否允許作為電子郵件模板?
這是我的頁面
@inherits ViewPage
@{
Layout = "_Layout";
ViewBag.Title = "";
}
<div class="container w-420 p-15 bg-white mt-40">
<div style="border-top:3px solid #22BCE5"> </div>
<span style="font-family:Arial;font-size:10pt">
Hello <b>{UserName}</b>,<br /><br />
Thanks for Registering to XYZ Portal<br /><br />
<a style="color:#22BCE5" href="{Url}">Click to Confirm Email</a><br />
<br /><br />
Thanks<br />
Admin (XYZ)
</span>
更新..
using (StreamReader reader = new StreamReader(HttpContext.Current.Server.MapPath("~/ContentPages/EmailConfTemplate.cshtml")))
{
body = reader.ReadToEnd();
//Replace UserName and Other variables available in body Stream
body = body.Replace("{UserName}", FirstName);
}
后來我將 SMTP 代碼替換為 ..
MailMessage message = new MailMessage(
ApplicationWideData.fromEmailId, // From field
ToEmailId, // Recipient field
"Click On HyperLink To Verify Email Id", // Subject of the email message
body
);
電子郵件只能理解兩種格式:純文本和 HTML。 由於 Razor 兩者都不是,因此需要由某些引擎處理它,以便將生成的 HTML 返回給您。
這正是您在 ASP.NET MVC 中使用 Razor 時在幕后發生的情況。 Razor 文件被編譯成一個內部 C# 類,它被執行,執行的結果是 HTML 的字符串內容,它被發送到客戶端。
您的問題是您想要並且需要運行該處理,只是為了將 HTML 作為字符串返回,而不是發送到瀏覽器。 之后,您可以對 HTML 字符串執行任何您想要的操作,包括將其作為電子郵件發送。
有幾個包包含這種功能,我已經成功地使用了Westwind.RazorHosting ,但您也可以使用RazorEngine獲得類似的結果。 我更喜歡 RazorHosting 用於獨立的非 Web 應用程序,而 RazorEngine 用於 Web 應用程序
這是我的一些代碼的(凈化)版本 - 我正在使用 Westwind.RazorHosting 使用強類型視圖從 Windows 服務發送剃刀格式的電子郵件。
RazorFolderHostContainer host = = new RazorFolderHostContainer();
host.ReferencedAssemblies.Add("NotificationsManagement.dll");
host.TemplatePath = templatePath;
host.Start();
string output = host.RenderTemplate(template.Filename, model);
MailMessage mm = new MailMessage { Subject = subject, IsBodyHtml = true };
mm.Body = output;
mm.To.Add(email);
var smtpClient = new SmtpClient();
await smtpClient.SendMailAsync(mm);
您不需要任何特殊庫來將 Razor 視圖呈現為 ASP.NET MVC 應用程序中的字符串。
public static class ViewToStringRenderer
{
public static async Task<string> RenderViewToStringAsync<TModel>(IServiceProvider requestServices, string viewName, TModel model)
{
var viewEngine = requestServices.GetRequiredService(typeof(IRazorViewEngine)) as IRazorViewEngine;
ViewEngineResult viewEngineResult = viewEngine.GetView(null, viewName, false);
if (viewEngineResult.View == null)
{
throw new Exception("Could not find the View file. Searched locations:\r\n" + string.Join("\r\n", viewEngineResult.SearchedLocations));
}
else
{
IView view = viewEngineResult.View;
var httpContextAccessor = (IHttpContextAccessor)requestServices.GetRequiredService(typeof(IHttpContextAccessor));
var actionContext = new ActionContext(httpContextAccessor.HttpContext, new RouteData(), new ActionDescriptor());
var tempDataProvider = requestServices.GetRequiredService(typeof(ITempDataProvider)) as ITempDataProvider;
using var outputStringWriter = new StringWriter();
var viewContext = new ViewContext(
actionContext,
view,
new ViewDataDictionary<TModel>(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model },
new TempDataDictionary(actionContext.HttpContext, tempDataProvider),
outputStringWriter,
new HtmlHelperOptions());
await view.RenderAsync(viewContext);
return outputStringWriter.ToString();
}
}
}
在控制器中
string str = await ViewToStringRenderer.RenderViewToStringAsync(HttpContext.RequestServices, $"~/Views/Emails/MyEmailTemplate.cshtml", new MyEmailModel { Prop1 = "Hello", Prop2 = 23 });
在 Startup.cs 的ConfigureServices()
中
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
public static class ViewToStringRenderer
{
public static string RenderViewToString<TModel>(ControllerContext controllerContext, string viewName, TModel model)
{
ViewEngineResult viewEngineResult = ViewEngines.Engines.FindView(controllerContext, viewName, null);
if (viewEngineResult.View == null)
{
throw new Exception("Could not find the View file. Searched locations:\r\n" + viewEngineResult.SearchedLocations);
}
else
{
IView view = viewEngineResult.View;
using (var stringWriter = new StringWriter())
{
var viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary<TModel>(model), new TempDataDictionary(), stringWriter);
view.Render(viewContext, stringWriter);
return stringWriter.ToString();
}
}
}
}
然后,從控制器
ViewToStringRenderer.RenderViewToString(this.ControllerContext, "~/Views/Emails/MyEmailTemplate.cshtml", model);
獲得電子郵件內容后,可以使用MailMessage
和SmtpClient
輕松發送電子郵件。
你看過MVC Mailer
嗎?
這是一個可從 GitHub ( https://github.com/smsohan/MvcMailer ) 獲得的免費軟件包
也有一個分步指南https://github.com/smsohan/MvcMailer/wiki/MvcMailer-Step-by-Step-Guide
它也在 Nuget 上。 https://www.nuget.org/packages/MvcMailer
本質上,它會將您的剃刀視圖解析為 html。
查看 NuGet 上提供的 RazorEngine ( https://razorengine.codeplex.com/ ) 等剃須刀處理器。 它處理 razor 以創建輸出,然后將其用作電子郵件正文。
Mailzory項目是發送帶有 Razor 模板的電子郵件的一個有價值且方便的選擇。
// template path
var viewPath = Path.Combine("Views/Emails", "hello.cshtml");
// read the content of template and pass it to the Email constructor
var template = File.ReadAllText(viewPath);
var email = new Email(template);
// set ViewBag properties
email.ViewBag.Name = "Johnny";
email.ViewBag.Content = "Mailzory Is Funny";
// send email
var task = email.SendAsync("mailzory@outlook.com", "subject");
task.Wait()
該項目托管在 Github。 還有一個可用於 Mailzory 的nuget 包。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.