NVelocity没有找到模板

时间:2009-12-21 13:35:10

标签: asp.net nvelocity

我在ASP.NET MVC应用程序中使用NVelocity时遇到了一些困难。我正在使用它作为生成电子邮件的方式。

据我所知,我传递的细节都是正确的,但无法加载模板。

以下是代码:

private const string defaultTemplatePath = "Views\\EmailTemplates\\";

...

velocityEngine = new VelocityEngine();
basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, defaultTemplatePath);
ExtendedProperties properties = new ExtendedProperties();
properties.Add(RuntimeConstants.RESOURCE_LOADER, "file");
properties.Add(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, basePath);
velocityEngine.Init(properties);

basePath是正确的目录,我已将值粘贴到资源管理器中以确保它是正确的。

if (!velocityEngine.TemplateExists(name))
    throw new InvalidOperationException(string.Format("Could not find a template named '{0}'", name));


Template result = velocityEngine.GetTemplate(name);
上面的

'name'是上面定义为basePath的文件夹中的有效文件名。但是,TemplateExists返回false。如果我注释了条件输出并让它在GetTemplate方法调用上失败,则堆栈跟踪如下所示:

   at NVelocity.Runtime.Resource.ResourceManagerImpl.LoadResource(String resourceName, ResourceType resourceType, String encoding)
   at NVelocity.Runtime.Resource.ResourceManagerImpl.GetResource(String resourceName, ResourceType resourceType, String encoding)
   at NVelocity.Runtime.RuntimeInstance.GetTemplate(String name, String encoding)
   at NVelocity.Runtime.RuntimeInstance.GetTemplate(String name)
   at NVelocity.App.VelocityEngine.GetTemplate(String name)
...

我现在陷入了一些僵局。我觉得答案很明显,但我现在似乎无法看到它。

5 个答案:

答案 0 :(得分:5)

您是否考虑过使用Castle NVelocityTemplateEngine

从“TemplateEngine组件1.1 - 2009年9月29日”部分下载并参考以下程序集:

using Castle.Components.Common.TemplateEngine.NVelocityTemplateEngine;
using Castle.Components.Common.TemplateEngine;

然后你可以简单地打电话:

using (var writer = new StringWriter())
{
    _templateEngine.Process(data, string.Empty, writer, _templateContents);
    return writer.ToString();
}

其中:

  • _templateEngine 是您的NVelocityTemplateEngine
  • 数据是您的信息词典(我使用词典使我能够通过模板中的键($ objectKeyName)访问对象。
  • _templateContents 是实际的模板字符串本身。

我希望这对你有所帮助!

只是要添加,你会想把它放到一个返回字符串的静态方法中!

答案 1 :(得分:3)

最近出现此问题 - 需要使用模板文件的位置初始化NVelocity。在这种情况下,mergeValues是一种匿名类型,因此在我的模板中,我可以引用$Values.SomeItem

    private string Merge(Object mergeValues)
    {
        var velocity = new VelocityEngine();
        var props = new ExtendedProperties();
        props.AddProperty("file.resource.loader.path", @"D:\Path\To\Templates");
        velocity.Init(props);
        var template = velocity.GetTemplate("MailTemplate.vm");
        var context = new VelocityContext();
        context.Put("Values", mergeValues);

        using (var writer = new StringWriter())
        {
            template.Merge(context, writer);
            return writer.ToString();
        }
    }

答案 2 :(得分:2)

答案 3 :(得分:1)

好的 - 所以我设法让事情变得有效,但它有点像黑客并且不是我想要的任何解决方案,但它有一些工作。

基本上,我手动将模板加载到字符串中,然后将该字符串传递给velocityEngine.Evaluate()方法,该方法将结果写入给定的StringWriter。这样做的副作用是模板中的#parse指令不起作用,因为它仍然无法找到文件。

using (StringWriter writer = new StringWriter())
{
    velocityEngine.Evaluate(context, writer, templateName, template);
    return writer.ToString();
}

在上面的代码中,templateName是不相关的,因为它没有被使用。 template是包含从磁盘预加载的整个模板的字符串。

我仍然感谢任何更好的解决方案,因为我真的不喜欢这个。

答案 4 :(得分:0)

测试是最终的权威:

http://fisheye2.atlassian.com/browse/castleproject/NVelocity/trunk/src/NVelocity.Tests/Test/ParserTest.cs?r=6005#l122

或者您可以使用TemplateEngine component这是一个围绕NVelocity的薄包装,使事情变得更容易。