在C# MVC 5中,是否有任何内置的方式来创建电子邮件模板,从 .cshtml
文件?
我想编译 .cshtml
基于我们传入的模型,从而创建一个原始的 .html
字符串。
在C# MVC中,似乎编译是不可调用的。我们需要原始的HTML输出,因为我们正试图发送电子邮件。
如果可能的话,请避免在答案中使用第三方库--尽量在C#中坚持使用。
我试过的方法
Here-字符串可能是一个可能的解决方案,但它们可能会变得混乱和难以阅读。它们也不会像有一个 .cshtml
文件。
当然,你可以自己做这个。
选项1:使用 _partialViews
附带 dynamic model
和 渲染部分 或选择渲染为HTMLstring @Html.Partial(_PartialView,(ModelClass)View.Data)
备选方案2:在服务器端基于微信公众号选择建立你的模板。
这个 例子 正准备发送注册确认信息,在评论里面可以看到你可以在这里切换加载不同的HTML模板。
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
// var user = await _userManager.FindByEmailAsync(model.Email);
if (result.Succeeded)
{
// Send an email with this link
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Action(nameof(ConfirmEmail), "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
//Email from Email Template
string Message = "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>";
// string body;
var webRoot = _env.WebRootPath; //get wwwroot Folder
//Get TemplateFile located at wwwroot/Templates/EmailTemplate/Register_EmailTemplate.html
var pathToFile = _env.WebRootPath
+ Path.DirectorySeparatorChar.ToString()
+ "Templates"
+ Path.DirectorySeparatorChar.ToString()
+ "EmailTemplate"
+ Path.DirectorySeparatorChar.ToString()
+ "Confirm_Account_Registration.html";
var subject = "Confirm Account Registration";
var builder = new BodyBuilder();
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
{
builder.HtmlBody = SourceReader.ReadToEnd();
}
//{0} : Subject
//{1} : DateTime
//{2} : Email
//{3} : Username
//{4} : Password
//{5} : Message
//{6} : callbackURL
string messageBody = string.Format(builder.HtmlBody,
subject,
String.Format("{0:dddd, d MMMM yyyy}", DateTime.Now),
model.Email,
model.Email,
model.Password,
Message,
callbackUrl
);
await _emailSender.SendEmailAsync(model.Email, subject, messageBody);
ViewData["Message"] = $"Please confirm your account by clicking this link: <a href='{callbackUrl}' class='btn btn-primary'>Confirmation Link</a>";
ViewData["MessageValue"] = "1";
_logger.LogInformation(3, "User created a new account with password.");
return RedirectToLocal(returnUrl);
}
ViewData["Message"] = $"Error creating user. Please try again later";
ViewData["MessageValue"] = "0";
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
这个方法是我用来强烈地将模型输入到.cshtml中,然后让Razor将html渲染成一个变量,我可以在邮件正文中使用。
public string ProcessView<TModel>(string viewName, object model, ControllerContext controllerContext, ViewDataDictionary viewData, TempDataDictionary tempData)
{
Check.NullOrEmpty(viewName, "viewName", "View name is required.");
Check.Null(viewData, "viewData", "It might be nothing, but view data was null and the original .net code has a special case for it.");
var dictionary = new ViewDataDictionary(viewData)
{
Model = model,
};
using (var writer = new System.IO.StringWriter())
{
var hostView = new RazorView(controllerContext, "nothing", String.Empty, false, Enumerable.Empty<string>());
var tempContext = new ViewContext(controllerContext, hostView, viewData, tempData, writer);
var view = FindPartialView(tempContext, viewName);
var viewContext = new ViewContext(controllerContext, view, dictionary, tempData, writer);
view.Render(viewContext, writer);
return writer.ToString();
}
}
private static IView FindPartialView(ViewContext viewContext, string partialViewName)
{
var viewEngineCollection = ViewEngines.Engines;
ViewEngineResult result = viewEngineCollection.FindPartialView(viewContext, partialViewName);
if (result.View != null)
{
return result.View;
}
StringBuilder builder = new StringBuilder();
foreach (string str in result.SearchedLocations)
{
builder.AppendLine();
builder.Append(str);
}
throw new InvalidOperationException("Could not find view named:" + partialViewName + " The following locations where checked: " + builder);
}