【问题标题】:C# MVC 5 - How to create email templates using .cshtml?C# MVC 5 - 如何使用 .cshtml 创建电子邮件模板?
【发布时间】:2020-08-13 20:23:55
【问题描述】:

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

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

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

如果可能,请避免在答案中使用 3rd 方库 - 尝试坚持使用原始 C#。

我的尝试

Here-strings 可能是一种可能的解决方案,但它们可能会变得混乱且难以阅读。他们也不会显示与拥有.cshtml 文件相同的IDE linting。

【问题讨论】:

    标签: c# .net asp.net-mvc asp.net-mvc-5 .net-4.8


    【解决方案1】:

    您当然可以自己完成。

    选项 1:使用 _partialViewsdynamic modelrenderpartial 或选项以呈现为 HTML 字符串 @Html.Partial(_PartialView,(ModelClass)View.Data)

    选项 2:根据服务器端的用户/租户/选择构建模板。

    这个example 正准备发送注册确认信息,在 cmets 中您可以看到可以切换/加载不同 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);  
        }   
    

    【讨论】:

      【解决方案2】:

      这是我用来将模型强输入到 .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);
      }
      

      【讨论】:

        猜你喜欢
        • 2011-02-18
        • 1970-01-01
        • 1970-01-01
        • 2012-05-17
        • 2010-12-18
        • 1970-01-01
        • 2013-09-01
        • 2013-04-24
        • 1970-01-01
        相关资源
        最近更新 更多