.net core mvc利用razor模板引擎开发邮件模板功能

  前言:模板引擎渲染HTML的技术有很多,这里仅说明一下利用.net core下的mvc框架里的razor引擎怎么去做模板渲染功能。 在介绍之前,首先感谢磊哥的技术分享,得以让这篇文章成型。

  核心参考文章:

  Walkthrough: Creating an HTML Email Template with Razor and Razor Class Libraries

  https://github.com/scottsauber/RazorHtmlEmails

  a-razor引擎渲染HTML核心代码:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace MeShop.CRM.Domain.Services.Vip.Helper
{
    // Code from: https://github.com/aspnet/Entropy/blob/master/samples/Mvc.RenderViewToString/RazorViewToStringRenderer.cs
    public class RazorViewToStringRenderer : IRazorViewToStringRenderer
    {
        private IRazorViewEngine _viewEngine;
        private ITempDataProvider _tempDataProvider;
        private IServiceProvider _serviceProvider;

        public RazorViewToStringRenderer(
            IRazorViewEngine viewEngine,
            ITempDataProvider tempDataProvider,
            IServiceProvider serviceProvider)
        {
            _viewEngine = viewEngine;
            _tempDataProvider = tempDataProvider;
            _serviceProvider = serviceProvider;
        }

        public async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model)
        {
            var actionContext = GetActionContext();
            var view = FindView(actionContext, viewName);

            using (var output = new StringWriter())
            {
                var viewContext = new ViewContext(
                    actionContext,
                    view,
                    new ViewDataDictionary<TModel>(
                        metadataProvider: new EmptyModelMetadataProvider(),
                        modelState: new ModelStateDictionary())
                    {
                        Model = model
                    },
                    new TempDataDictionary(
                        actionContext.HttpContext,
                        _tempDataProvider),
                    output,
                    new HtmlHelperOptions());

                await view.RenderAsync(viewContext);

                return output.ToString();
            }
        }

        private IView FindView(ActionContext actionContext, string viewName)
        {
            var getViewResult = _viewEngine.GetView(executingFilePath: null, viewPath: viewName, isMainPage: true);
            if (getViewResult.Success)
            {
                return getViewResult.View;
            }

            var findViewResult = _viewEngine.FindView(actionContext, viewName, isMainPage: true);
            if (findViewResult.Success)
            {
                return findViewResult.View;
            }

            var searchedLocations = getViewResult.SearchedLocations.Concat(findViewResult.SearchedLocations);
            var errorMessage = string.Join(
                Environment.NewLine,
                new[] { $"Unable to find view '{viewName}'. The following locations were searched:" }.Concat(searchedLocations)); ;

            throw new InvalidOperationException(errorMessage);
        }

        private ActionContext GetActionContext()
        {
            var httpContext = new DefaultHttpContext();
            httpContext.RequestServices = _serviceProvider;
            return new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
        }

    }
    public interface IRazorViewToStringRenderer
    {
        Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model);
    }
}
View Code

  

  b-邮件模板模块:

  需要注意的是:邮件模板模块,必须放在mvc项目的Views目录下,主要是利用Razor寻找页面元素位置的机制(或者可以自定义寻找视图位置)

  TemplateShopExpired实体示例:

namespace MeShop.Module.Model.CRM.EmailTemplate
{
    /// <summary>
    /// 邮件模板类-店铺过期
    /// </summary>
    public class TemplateShopExpired
    {
        public string ShopHost { get; set; }
        public string ShopHostAdmin { get; set; }
        public string ShopSaveDays { get; set; }
        public string ShopCloseDate { get; set; }
        public string CdnHost { get; set; }
    }
}
View Code

  EmailTemplateShopExpired.cshtml文件示例:

@model MeShop.Module.Model.CRM.EmailTemplate.TemplateShopExpired
@{
    Layout = null;
}
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title></title>
</head>
<body>
    <table width="650" border="0" align="center" cellpadding="0" cellspacing="0" style="border: 1px solid #ccc;">
        <tbody>
            <tr>
                <td valign="top" width="335">
                    <span class="edit-emai-text" style="font-size:20px;color:#000;font-weight: bold;font-family: arial;display:block;padding:20px 0 20px 20px;">
                        <span class="edit-email-child">欢迎来到meshop</span>
                    </span>
                </td>
            </tr>
            <tr>
                <td valign="top" width="335">
                    <span class="edit-emai-text" style="font-size:15px;color:#000;font-weight:bold;font-family: arial;display:block;padding:20px 20px 15px 20px;">
                        <span class="edit-email-child">您的店铺<a href="@(Model.ShopHost)/admin/home">@(Model.ShopHostAdmin)</a>已经到期, 我们将为您保留@ShopSaveDays@天的店铺配置数据,@(Model.ShopCloseDate)(UTC)后我们将清除店铺的配置数据,只保留店铺注册信息。</span>
                    </span>
                </td>
            </tr>
            <tr>
                <td valign="top" width="335">
                    <span class="edit-emai-text" style="font-size:16px;color:#000;font-weight:bold;font-family: arial;display:block;padding:20px 0 15px 20px;">
                        <a class="edit-emai-link" href="@(Model.ShopHost)/admin/home" title="" style="border:1px solid #ccc;font-size:14px;border-radius: 3px; padding:5px 3px; color:#000; text-decoration:none"><span class="edit-email-child"> 立即续费 </span></a>
                    </span>
                </td>
            </tr>
        </tbody>
    </table>
    <TABLE style="PADDING-BOTTOM: 10px; FONT-FAMILY: Arial; MARGIN-BOTTOM: 10px; MARGIN-LEFT: auto; FONT-SIZE: 12px; MARGIN-RIGHT: auto; PADDING-TOP: 15px" border=0 cellSpacing=0 cellPadding=0 width=650 bgColor=#ffffff align=center>
        <TBODY>
            <TR>
                <TD vAlign=center width=650 align=middle>
                    <SPAN class="edit-emai-text" style="PADDING-BOTTOM:15px; DISPLAY: inline-block;vertical-align: middle;">
                        <img src="@(Model.CdnHost)/admin/favicon.ico" style="display:inline-block;40px;height:auto; vertical-align: middle;">
                        <span class="edit-emai-text" style=" DISPLAY: inline-block;FONT-SIZE:20px;font-weight:bold;">meshop</span>
                    </SPAN>
                </TD>
            </TR>
        </TBODY>
    </TABLE>
</body>
</html>
View Code

  c-使用示例:

/// <summary>
/// 3-发送店铺过期邮件
/// </summary>
/// <param name="shopID">店铺ID</param>
/// <param name="times">次数</param>
public async Task SendShopExpiredEmail(long shopID, int times)
{
    ShopInfo shopInfo = base.ShopInfoRepository.Get(shopID);
    if (shopInfo != null)
    {
        string shopSsoHost = PayCommonHelper.GetSsoHost(shopInfo.HostAdmin);

        //生成店铺过期时间执行SouceValue(店铺ID+过期时间+次数)
        string shopExpiredSourceValue = $"{shopID}_{shopInfo.ExpiredTime.ToString_yyyyMMddHHmmss()}_{times}";

        TemplateShopExpired templateShopExpired = new TemplateShopExpired
        {
            ShopHostAdmin = shopInfo.HostAdmin,
            ShopHost = shopSsoHost,
            ShopSaveDays = (shopInfo.BufferTime - shopInfo.ExpiredTime).Days.ToString(),
            ShopCloseDate = shopInfo.BufferTime.ToString_yyyyMMddHHmmss(),
            CdnHost = PayCommonHelper.GetCdnHost(this._config)
        };

        string emailTemplateContent = await this._razorViewToStringRenderer.RenderViewToStringAsync(this._emailTmplateShopExpiredRazorPath, templateShopExpired);
    }
}
View Code
*感谢您的阅读。喜欢的、有用的就请大哥大嫂们高抬贵手“推荐一下”吧!你的精神 支持是博主强大的写作动力。欢迎转载!
*博主的文章是自己平时开发总结的经验,由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。
*我的博客: http://www.cnblogs.com/lxhbky/
原文地址:https://www.cnblogs.com/lxhbky/p/14639334.html