Asp.net mvc 4 尝试发送电子邮件时出现RazoEngine错误

Asp.net mvc 4 尝试发送电子邮件时出现RazoEngine错误,asp.net-mvc-4,razorengine,Asp.net Mvc 4,Razorengine,我有一个MVC4应用程序,可以发送多封电子邮件。例如,我有一个用于提交订单的电子邮件模板,一个用于取消订单的模板,等等 我有一个电子邮件服务,有多种方法。我的控制器调用Send方法,如下所示: public virtual void Send(List<string> recipients, string subject, string template, object data) { ... string html = GetContent(template, da

我有一个MVC4应用程序,可以发送多封电子邮件。例如,我有一个用于提交订单的电子邮件模板,一个用于取消订单的模板,等等

我有一个
电子邮件服务
,有多种方法。我的控制器调用
Send
方法,如下所示:

public virtual void Send(List<string> recipients, string subject, string template, object data)
{
    ...
    string html = GetContent(template, data);
    ...
}
我收到错误信息:

同一密钥已用于另一个模板

在我的
GetContent
方法中,我是否应该为
TemplateKey
添加一个新参数,并使用该变量,而不是始终使用
htmlTemplate
?然后,
neworder电子邮件模板
可以为用于取消订单的电子邮件模板提供
newOrderKey
CancelOrderKey
这是因为您对多个不同的模板使用相同的模板键(
“htmlTemplate”
)。 请注意,您当前实现
GetContent
的方式将遇到多个问题:

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

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

解决方案: 实现管理模板的界面:

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的贡献者)

非常感谢您,这非常有帮助!我实现了
ITemplateManager
接口,并像您所说的那样删除了
GetContent
方法。您上面提到的启动时设置部分是否进入了
Send()
?它应该在应用程序设置中使用
Engine.Razor
属性执行一次
,然后执行一次
。但是具体位置取决于您的应用程序:例如,使用静态构造函数,或者在控制台应用程序中将其添加到
Main
的开头,这是正确的!使用这种设置,您还可以在
应用程序\u Start()
中预编译所有模板(如果您愿意,这会将发送第一封电子邮件时的初始编译时间延迟移到启动时间)。在执行此操作时,您在启动时使用
Compile
,并在
GetContent
@Mvcdev中使用
RunCompile
而不是
。谢谢我个人认为这个API过于复杂,应该像
string content=razorEngine.Run(templateFile,model)一样简单
// You don't really need this method anymore.
private string GetContent(string template, object data)
{
    return Engine.Razor.RunCompile(template, null, data);
}