NVelocity не находит шаблон

У меня возникли трудности с использованием NVelocity в приложении ASP.NET MVC. Я использую его как способ создания электронных писем.

Насколько я могу разобрать, все детали, которые я передаю, верны, но не удается загрузить шаблон.

Вот код:

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)
...

Я сейчас в тупике. Я чувствую, что ответ ослепляюще очевиден, но сейчас я просто не вижу его.


person Colin Mackay    schedule 21.12.2009    source источник
comment
Нарушил ли я какое-то неписаное правило, согласно которому тег ASP.NET MVC (среди прочего) был удален?   -  person Colin Mackay    schedule 21.12.2009
comment
Я удалил тег asp.net, потому что он вообще не имеет отношения к asp.net.   -  person Mauricio Scheffer    schedule 21.12.2009
comment
Эммм ... Тег ASP.NET остался. Возможно, вы имели в виду ASP.NET MVC. Если это не связано с ASP.NET MVC, как оно все еще связано с ASP.NET?   -  person Colin Mackay    schedule 22.12.2009
comment
Кто-то вернул метку после того, как я ее удалил.   -  person Mauricio Scheffer    schedule 01.01.2010


Ответы (5)


Думали ли вы об использовании NVelocityTemplateEngine от Castle?

Загрузите из раздела «Компонент TemplateEngine 1.1 - 29 сентября 2009 г.» и укажите следующие сборки:

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
  • data - это ваш Словарь информации (я использую Словарь, чтобы позволить мне получать доступ к объектам с помощью ключа ($ objectKeyName) в моем шаблоне.
  • _templateContents - это сама строка шаблона.

Надеюсь, это вам поможет!

Просто чтобы добавить, вы, конечно же, захотите поместить это в статический метод, возвращающий строку!

person Robert Reid    schedule 22.01.2010

Была эта проблема недавно - 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();
        }
    }
person David Clarke    schedule 20.08.2010

Попробуйте установить file.resource.loader.path

http://weblogs.asp.net/george_v_reilly/archive/2007/03/06/img-srchttpwwwcodegenerationnetlogosnveloc.aspx

person Scott    schedule 24.05.2010

Итак, мне удалось заставить что-то работать, но это немного похоже на взлом, и я не могу найти решение, которое мне нужно, но у него есть что-то работающее.

По сути, я вручную загружаю шаблон в строку, а затем передаю эту строку методу velocityEngine.Evaluate (), который записывает результат в заданный StringWriter. Побочным эффектом этого является то, что инструкции #parse в шаблоне не работают, потому что он по-прежнему не может найти файлы.

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

В приведенном выше коде templateName не имеет значения, так как не используется. template - это строка, содержащая весь шаблон, предварительно загруженный с диска.

Я все еще был бы признателен за любые лучшие решения, поскольку мне это действительно не нравится.

person Colin Mackay    schedule 21.12.2009
comment
Правильно, это способ использовать базовый движок только как текст. ЭТИ, ребята из Java, сумасшедшие идеи ... Вот почему Касл создал этот проект NVelocityTemplateEngine - это набор абстракций вокруг того, что вы здесь разместили. - person eduncan911; 08.10.2010

Испытания являются высшим авторитетом:

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

Или вы можете использовать компонент TemplateEngine, который представляет собой тонкую оболочку вокруг NVelocity, которая делает все проще.

person Mauricio Scheffer    schedule 31.12.2009