[英]Send Scheduled Email using email Templates in .NET MVC3 using C#
[英]C# MVC 5 - How to create email templates using .cshtml?
在 C# MVC 5 中,是否有任何内置方法可以从.cshtml
文件创建 email 模板?
我想根据我们传入的 model 编译.cshtml
,从而创建一个原始的.html
字符串。
看来编译在 C# MVC 中是不可调用的。 我们需要原始的 HTML output 因为我们正在尝试发送电子邮件。
如果可能,请避免在答案中使用第 3 方库 - 尝试坚持使用香草 C#。
我试过的
Here-strings 可能是一种可能的解决方案,但它们可能会变得混乱且难以阅读。 他们也不会显示与具有.cshtml
文件相同的 IDE linting。
你绝对可以自己做。
选项 1 :使用带有dynamic model
_partialViews
_partialViews和渲染部分到或渲染到 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);
}
This is a method I use to strongly type a model to a.cshtml and get Razor to render html as a variable I can use with email bodies.
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.