2009-12-21 79 views
4

我在ASP.NET MVC應用程序中使用NVelocity時遇到了一些困難。我使用它作爲生成電子郵件的一種方式。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); 

的基本路徑是正確的目錄,我已經粘貼值轉換成資源管理器,以確保它是正確的。

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


Template result = velocityEngine.GetTemplate(name); 

「名稱」是以上所定義如上基本路徑的文件夾中有效的文件名。但是,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) 
... 

我現在是在有點陷入僵局。我覺得答案是非常明顯的,但我目前似乎無法看到它。

+0

難道我違背了一些不成文的規則,即ASP.NET MVC的標籤(等等)移除? – 2009-12-21 14:36:58

+0

我刪除了asp.net標籤,因爲這完全與asp.net無關。 – 2009-12-21 16:26:08

+0

嗯...... ASP.NET標籤仍然存在。你的意思是ASP.NET MVC。如果它與ASP.NET MVC沒有關係,它又如何與ASP.NET相關? – 2009-12-22 15:04:37

回答

1

好吧 - 所以我設法找到一些工作,但它有點破解,並沒有接近我想要的解決方案,但它有一些工作。

基本上,我手動將模板加載到字符串中,然後將該字符串傳遞給velocityEngine.Evaluate()方法,該方法將結果寫入給定的StringWriter。這樣做的副作用是模板中的#parse指令不起作用,因爲它仍然無法找到文件。

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

在上面的代碼中,templateName是不相關的,因爲它沒有被使用。模板是包含從磁盤預先加載的整個模板的字符串。

我還是很欣賞任何更好的解決方案,因爲我真的不喜歡這個。

+0

沒錯,這是僅將文本引擎用作文本的方式。這些Java傢伙,瘋狂的想法......這就是爲什麼Castle創建了NVelocityTemplateEngine項目的原因 - 這是圍繞你在這裏發佈的一系列抽象概念。 – eduncan911 2010-10-08 04:05:15

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
  • 數據是你的Dictio (我正在使用Dictionary來讓我通過模板中的鍵($ objectKeyName)訪問對象。
  • _templateContents是實際的模板字符串本身。

我希望這對你有幫助!

只要添加,你會想把它放到一個返回字符串的靜態方法當然!

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(); 
     } 
    } 
+0

這對我來說非常合適。謝謝 – scottm 2010-09-10 18:53:37