尝试发送电子邮件时 RazorEngine 错误

RazorEngine Error trying to send email

我有一个发送多封电子邮件的 MVC 4 应用程序。比如我有一个提交订单的邮件模板,一个取消订单的模板等等...

我有一个 Email Service 有多种方法。我的控制器调用 Send 方法,如下所示:

public virtual void Send(List<string> recipients, string subject, string template, object data)
{
    ...
    string html = GetContent(template, data);
    ...
}

Send方法调用了GetContent,这是导致问题的方法:

private string GetContent(string template, object data)
{
    string path = Path.Combine(BaseTemplatePath, string.Format("{0}{1}", template, ".html.cshtml"));
    string content = File.ReadAllText(path);
    return Engine.Razor.RunCompile(content, "htmlTemplate", null, data);
}

我收到错误消息:

The same key was already used for another template!

在我的 GetContent 方法中,我应该为 TemplateKey 添加一个新参数并使用该变量而不是总是使用 htmlTemplate 吗?那么 new order email template 可以有 newOrderKeyCancelOrderKey 作为用于取消订单的电子邮件模板?

说明

发生这种情况是因为您对多个不同的模板使用了相同的模板密钥 ("htmlTemplate")。 请注意,您目前实施的方式 GetContent 您将 运行 陷入多个问题:

  • 即使使用唯一键,例如template变量,在磁盘上编辑模板时也会触发异常。

  • 性能:即使模板已经缓存,您每次都在读取模板文件。

解决方案:

实施 ITemplateManager 界面来管理您的模板:

public class MyTemplateManager : ITemplateManager
{
    private readonly string baseTemplatePath;
    public MyTemplateManager(string basePath) {
      baseTemplatePath = basePath;
    }

    public ITemplateSource Resolve(ITemplateKey key)
    {
        string template = key.Name;
        string path = Path.Combine(baseTemplatePath, string.Format("{0}{1}", template, ".html.cshtml"));
        string content = File.ReadAllText(path);
        return new LoadedTemplateSource(content, path);
    }

    public ITemplateKey GetKey(string name, ResolveType resolveType, ITemplateKey context)
    {
        return new NameOnlyTemplateKey(name, resolveType, context);
    }

    public void AddDynamic(ITemplateKey key, ITemplateSource source)
    {
        throw new NotImplementedException("dynamic templates are not supported!");
    }
}

启动时设置:

var config = new TemplateServiceConfiguration();
config.Debug = true;
config.TemplateManager = new MyTemplateManager(BaseTemplatePath); 
Engine.Razor = RazorEngineService.Create(config);

并使用它:

// You don't really need this method anymore.
private string GetContent(string template, object data)
{
    return Engine.Razor.RunCompile(template, null, data);
}

RazorEngine 现在将在内部修复上述所有问题。请注意使用模板的名称作为键是多么完美,如果在您的场景中您只需要名称来识别模板(否则您不能使用 NameOnlyTemplateKey 并且需要提供您自己的实现)。

希望这对您有所帮助。 (免责声明:RazorEngine 的贡献者)