繁体   English   中英

C# MVC 5 - 如何使用.cshtml 创建 email 模板?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM