简体   繁体   English

Razor 视图页面作为电子邮件模板

[英]Razor View Page as Email Template

I have designed an Email Template from Razor Syntax.我从 Razor 语法设计了一个电子邮件模板。 When I send this template as Email using C# code and SMTP protocol, I get bare Razor and HTML markups as Email Body.当我使用 C# 代码和 SMTP 协议将此模板作为电子邮件发送时,我得到裸露的 Razor 和 HTML 标记作为电子邮件正文。 Am I wrong in this approach?这种方法我错了吗? Are Razor Pages allowed as Email Template? Razor 页面是否允许作为电子邮件模板?

Here is my Page这是我的页面

@inherits ViewPage
@{
Layout = "_Layout";
ViewBag.Title = "";
}
<div class="container w-420 p-15 bg-white mt-40">
<div style="border-top:3px solid #22BCE5">&nbsp;</div>
<span style="font-family:Arial;font-size:10pt">
    Hello <b>{UserName}</b>,<br /><br />
    Thanks for Registering to XYZ Portal<br /><br />
    <a style="color:#22BCE5" href="{Url}">Click to Confirm Email</a><br />

    <br /><br />
    Thanks<br />
    Admin (XYZ)
</span>

Update..更新..

 using (StreamReader reader = new StreamReader(HttpContext.Current.Server.MapPath("~/ContentPages/EmailConfTemplate.cshtml")))
  {
     body = reader.ReadToEnd();
     //Replace UserName and Other variables available in body Stream
     body = body.Replace("{UserName}", FirstName);

  }

Later On I am replacing the SMTP Code as ..后来我将 SMTP 代码替换为 ..

  MailMessage message = new MailMessage(
    ApplicationWideData.fromEmailId, // From field
    ToEmailId, // Recipient field
    "Click On HyperLink To Verify Email Id", // Subject of the email message
    body
   );

Email messages only understand two formats: plain text and HTML.电子邮件只能理解两种格式:纯文本和 HTML。 Since Razor is neither, it will need to be processed by some engine, so that it gives you back the generated HTML.由于 Razor 两者都不是,因此需要由某些引擎处理它,以便将生成的 HTML 返回给您。

That's exactly what happens when you use Razor in ASP.NET MVC, behind the scenes.这正是您在 ASP.NET MVC 中使用 Razor 时在幕后发生的情况。 The Razor file is compiled into a internal C# class, that gets executed, and the result of the execution is the string content of the HTML, that gets sent to the client. Razor 文件被编译成一个内部 C# 类,它被执行,执行的结果是 HTML 的字符串内容,它被发送到客户端。

Your problem is that you want and need that processing to run, only to get the HTML back as a string, instead of being sent to the browser.您的问题是您想要并且需要运行该处理,只是为了将 HTML 作为字符串返回,而不是发送到浏览器。 After that you can do whatever you want with the HTML string, including sending it as an e-mail.之后,您可以对 HTML 字符串执行任何您想要的操作,包括将其作为电子邮件发送。

There are several packages that include this power, and I've used Westwind.RazorHosting successfully, but you can also use RazorEngine with similar results.有几个包包含这种功能,我已经成功地使用了Westwind.RazorHosting ,但您也可以使用RazorEngine获得类似的结果。 I would prefer RazorHosting for standalone non-web applications, and RazorEngine for web applications我更喜欢 RazorHosting 用于独立的非 Web 应用程序,而 RazorEngine 用于 Web 应用程序

Here is a (sanitized) version of some of my code - I'm using Westwind.RazorHosting to send razor-formatted emails from a windows service, using a strongly typed view.这是我的一些代码的(净化)版本 - 我正在使用 Westwind.RazorHosting 使用强类型视图从 Windows 服务发送剃刀格式的电子邮件。

RazorFolderHostContainer host = = new RazorFolderHostContainer();
host.ReferencedAssemblies.Add("NotificationsManagement.dll");
host.TemplatePath = templatePath;
host.Start();
string output = host.RenderTemplate(template.Filename, model);

MailMessage mm = new MailMessage { Subject = subject, IsBodyHtml = true };
mm.Body = output;
mm.To.Add(email);

var smtpClient = new SmtpClient();
await smtpClient.SendMailAsync(mm);

You do not need any special libraries to render a Razor view to a string in an ASP.NET MVC application.您不需要任何特殊库来将 Razor 视图呈现为 ASP.NET MVC 应用程序中的字符串。

Here is how you do it in MVC Core 3以下是您在 MVC Core 3 中的操作方法

public static class ViewToStringRenderer
{
    public static async Task<string> RenderViewToStringAsync<TModel>(IServiceProvider requestServices, string viewName, TModel model)
    {
        var viewEngine = requestServices.GetRequiredService(typeof(IRazorViewEngine)) as IRazorViewEngine;
        ViewEngineResult viewEngineResult = viewEngine.GetView(null, viewName, false);
        if (viewEngineResult.View == null)
        {
            throw new Exception("Could not find the View file. Searched locations:\r\n" + string.Join("\r\n", viewEngineResult.SearchedLocations));
        }
        else
        {
            IView view = viewEngineResult.View;
            var httpContextAccessor = (IHttpContextAccessor)requestServices.GetRequiredService(typeof(IHttpContextAccessor));
            var actionContext = new ActionContext(httpContextAccessor.HttpContext, new RouteData(), new ActionDescriptor());
            var tempDataProvider = requestServices.GetRequiredService(typeof(ITempDataProvider)) as ITempDataProvider;

            using var outputStringWriter = new StringWriter();
            var viewContext = new ViewContext(
                actionContext,
                view,
                new ViewDataDictionary<TModel>(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model },
                new TempDataDictionary(actionContext.HttpContext, tempDataProvider),
                outputStringWriter,
                new HtmlHelperOptions());

            await view.RenderAsync(viewContext);

            return outputStringWriter.ToString();
        }
    }
}

In the controller在控制器中

string str = await ViewToStringRenderer.RenderViewToStringAsync(HttpContext.RequestServices, $"~/Views/Emails/MyEmailTemplate.cshtml", new MyEmailModel { Prop1 = "Hello", Prop2 = 23 });

In ConfigureServices() in Startup.cs在 Startup.cs 的ConfigureServices()

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

Here is how you do it in MVC 5这是您在 MVC 5 中的操作方法

public static class ViewToStringRenderer
{
    public static string RenderViewToString<TModel>(ControllerContext controllerContext, string viewName, TModel model)
    {
        ViewEngineResult viewEngineResult = ViewEngines.Engines.FindView(controllerContext, viewName, null);
        if (viewEngineResult.View == null)
        {
            throw new Exception("Could not find the View file. Searched locations:\r\n" + viewEngineResult.SearchedLocations);
        }
        else
        {
            IView view = viewEngineResult.View;

            using (var stringWriter = new StringWriter())
            {
                var viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary<TModel>(model), new TempDataDictionary(), stringWriter);
                view.Render(viewContext, stringWriter);

                return stringWriter.ToString();
            }
        }
    }
}

Then, from the controller然后,从控制器

ViewToStringRenderer.RenderViewToString(this.ControllerContext, "~/Views/Emails/MyEmailTemplate.cshtml", model);

After you have the email content, it is easy to send the email using MailMessage and SmtpClient .获得电子邮件内容后,可以使用MailMessageSmtpClient轻松发送电子邮件。

Have you took a look at MVC Mailer ?你看过MVC Mailer吗?

It's a free package available from GitHub ( https://github.com/smsohan/MvcMailer )这是一个可从 GitHub ( https://github.com/smsohan/MvcMailer ) 获得的免费软件包

There is a step by step guide for it too https://github.com/smsohan/MvcMailer/wiki/MvcMailer-Step-by-Step-Guide也有一个分步指南https://github.com/smsohan/MvcMailer/wiki/MvcMailer-Step-by-Step-Guide

It's also on Nuget too.它也在 Nuget 上。 https://www.nuget.org/packages/MvcMailer https://www.nuget.org/packages/MvcMailer

Essentially it will parse your razor view into html.本质上,它会将您的剃刀视图解析为 html。

Check out a razor processor like RazorEngine ( https://razorengine.codeplex.com/ ) which is available on NuGet.查看 NuGet 上提供的 RazorEngine ( https://razorengine.codeplex.com/ ) 等剃须刀处理器。 It processes razor to create an output, which is what you'd then use as the body of your email.它处理 razor 以创建输出,然后将其用作电子邮件正文。

The Mailzory project is a valuable and convenient choice for sending emails which have Razor templates. Mailzory项目是发送带有 Razor 模板的电子邮件的一个有价值且方便的选择。

// template path
var viewPath = Path.Combine("Views/Emails", "hello.cshtml");
// read the content of template and pass it to the Email constructor
var template = File.ReadAllText(viewPath);

var email = new Email(template);

// set ViewBag properties
email.ViewBag.Name = "Johnny";
email.ViewBag.Content = "Mailzory Is Funny";

// send email
var task = email.SendAsync("mailzory@outlook.com", "subject");
task.Wait()

this project is hosted at Github.该项目托管在 Github。 Also there is a nuget package available for Mailzory.还有一个可用于 Mailzory 的nuget 包

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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