C# MVC 5 - 如何使用.cshtml创建电子邮件模板?

问题描述 投票:0回答:1

在C# MVC 5中,是否有任何内置的方式来创建电子邮件模板,从 .cshtml 文件?

我想编译 .cshtml 基于我们传入的模型,从而创建一个原始的 .html 字符串。

在C# MVC中,似乎编译是不可调用的。我们需要原始的HTML输出,因为我们正试图发送电子邮件。

如果可能的话,请避免在答案中使用第三方库--尽量在C#中坚持使用。

我试过的方法

Here-字符串可能是一个可能的解决方案,但它们可能会变得混乱和难以阅读。它们也不会像有一个 .cshtml 文件。

c# .net asp.net-mvc asp.net-mvc-5 .net-4.8
1个回答
0
投票

当然,你可以自己做这个。

选项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);  
    }   

0
投票

这个方法是我用来强烈地将模型输入到.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);
}
© www.soinside.com 2019 - 2024. All rights reserved.