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

时间:2015-04-22 16:24:59

标签: asp.net-mvc-4 razorengine

我有一个发送多封电子邮件的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);
}

我收到错误:

  

相同的密钥已用于另一个模板!

在我的GetContent方法中,我应该为TemplateKey添加新参数并使用该变量而不是始终使用htmlTemplate吗?然后new order email template可能会有newOrderKeyCancelOrderKey用于取消订单的电子邮件模板吗?

1 个答案:

答案 0 :(得分:17)

解释

这是因为您对多个不同的模板使用相同的模板密钥("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并需要提供自己的实现)。 / p>

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