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

问题描述 投票:0回答:2

我有一个发送多封电子邮件的 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
可以有
newOrderKey
CancelOrderKey
用于取消订单的电子邮件模板吗?

asp.net-mvc-4 razorengine
2个回答
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
并且需要提供您自己的实现)。

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


0
投票

就像对最终到达这里的人的答案一样,您还可以使用 Engine.Razor.IsTemplateCached 方法在 .Run 和 .RunCompile 之间进行选择

 private static string GetEmailBody(string template, EmailClass model)
  {
      string emailBody = Task.Run(() =>
      {
          if (Engine.Razor.IsTemplateCached("T" + model.Type.ToString(), model.GetType()))
          {
              return Engine.Razor.Run("T" + model.Type.ToString(), typeof(EmailClass ), model);
          }
          else
          {
              return Engine.Razor.RunCompile(template, "T" + model.Type.ToString(), typeof(EmailClass ), model);

          }            

      }).Result;
      
     
      return emailBody;
  }
© www.soinside.com 2019 - 2024. All rights reserved.