[转] Template merging with NVelocity and ASP.NET
Posted on 2006-08-30 07:12 剑廿三 阅读(1832) 评论(0) 编辑 收藏 举报http://www.codeproject.com/useritems/nvelocityaspnet.asp
| |||||||||||
IntroductionIf you ever tried to implement a newsletter system or a service for communicating with website users you have probably faced the requisite to send multiple email messages with a common template and some differences, like a personalized greeting in the message header, or an unsubscribe link with a personalized querystring. Maybe the first way to accomplish this is by writing the static parts of the message in plain text files - for example emailheader.txt, emailfooter.txt - and reassemble them in the code, merging the varying parts, like recipient's name, surname, personalized querystring link, and so on. But what about having a template engine which, given a template - be it a file on the filesystem, an assembly embedded resource or an in-memory object - and the information we want to merge in the template, did this all for us? "NVelocity[^] is a .Net-based template engine. It permits anyone to use the simple yet powerful template language to reference objects defined in .Net code. The purpose of this project is to port the Jakarta Velocity[^] project to Microsoft .Net (written in C#)." Going back to the newsletter example, using NVelocity the the developer just needs to:
NVelocity will do the rest. BackgroundIn order to write NVelocity templates a basic knowledge of the language it uses would be helpful. Anyway in email templates it's rarely necessary to write loops, methods or branch conditions, instead more often the need is to replace single variables with values provided programmatically. In this article I'm going to show a simple way of writing templates, but if you think that you need something more complex my advice is to read the VTL Refence Guide[^]. The notation for variables, as taken from the VTL Reference guide, is the following:Notation (variable name): $ [ ! ][ { ][ a..z, A..Z ][ a..z, A..Z, 0..9, -, _ ][ } ] Examples:
About the articleIn this article I am going to show how I implemented a wrapper for NVelocity functionalities, which simplifies merging templates coming from filesystem, assembly resources or in-memory objects, and will build a simple web project for demonstration. As a note, keep in mind that the wrapper can be used in any other project type, from console applications to WindowsForms and WebServices as well. I have chosen to build the demo in ASP.NET because it is a good compromise between nice user interface and ease of creation. Using the codeThe main access point is the class The three correspondent engine types are All of the inherit from the Since implementing the In the first case the two input parameters are the In the second case the additional parameter is a The templateTo use the three types of engines we need to create a template to be merged. Using VTL syntax, we write a simple template which can be used to render a message containing a simple personalized greeting, along with the date when the merging has been done. To test all of the three engines the demo project contains a template file placed on the filesystem, a template file embedded in the assembly as a resource, and an in-memory template (a string) created at runtime. To write a template file we just need to open a text editor and save the file with the .vm extension. Hi $name $surname, this output has been generated from a $templateType template on $date. This is a very simple template, but it's not difficult to imagine in its place an entire html email with nice formatting and some images.
Using the wrapper along with the templatesNow all we need to do is:
File templateSupposing we have placed the template file in a subdirectory called Templates in the root folder of our web project and named it SimpleTemplate.vm: string templateDir = HttpContext.Current.Server.MapPath("Templates");
string templateName = "SimpleTemplate.vm";
INVelocityEngine fileEngine =
NVelocityEngineFactory.CreateNVelocityFileEngine(templateDir, true);
IDictionary context = new Hashtable();
context.Add("name", TextBox1.Text);
context.Add("surname", TextBox2.Text);
context.Add("templateType", "file");
context.Add("date", DateTime.Now.ToString("D"));
LabelMergedFile.Text = fileEngine.Process(context, templateName);
The Embedded resource templateSupposing we have placed the template file in a subdirectory called Embedded resources in the root folder of our web project, named it SimpleTemplate.vm and marked it as embedded resource: string assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
INVelocityEngine embeddedEngine =
NVelocityEngineFactory.CreateNVelocityAssemblyEngine(assemblyName, true);
IDictionary context = new Hashtable();
context.Add("name", TextBox1.Text);
context.Add("surname", TextBox2.Text);
context.Add("templateType", "embedded");
context.Add("date", DateTime.Now.ToString("D"));
LabelMergedEmbedded.Text =
embeddedEngine.Process(context, "EmbeddedResources.SimpleTemplate.vm");
Note that when calling the In-memory templateDifferently from the previous cases, now the template must reside in memory, so we create a string object that contains the template: string template = "Hi $name $surname, this output has been generated from a $templateType template on $date.";
INVelocityEngine memoryEngine =
NVelocityEngineFactory.CreateNVelocityMemoryEngine(true);
IDictionary context = new Hashtable();
context.Add("name", TextBox1.Text);
context.Add("surname", TextBox2.Text);
context.Add("templateType", "memory");
context.Add("date", DateTime.Now.ToString("D"));
LabelMergedMemory.Text = memoryEngine.Process(context, template);
Note that the keys of the objects you place in the IDictionary object must correspond to the variable's names specified in the template if you want NVelocity to merge them. In case you forget to supply a key whose corresponding variable is contained in the template NVelocity just forgets about it and will give in output $variablename. Points of InterestI wrote this brief tutorial because me myself have been looking for something like this while I was implementing a newsletter service, and after getting crazy at trying to merge the templates by hand.
NVelocity can do much more than this anyway, and if you want to find a place where NVelocity is truly "milked" you should take a look at CastleProject[^], where they use it as a view engine in their MonoRail[^] project. The sad thing about NVelocity is that the project is almost dead; the latest release, 0.4.2, is dated October 27, 2003. The positive thing is that CastleProject developers have made a fork of the project, fixed some bugs and killed a tedious assembly dependence on an old Log4Net distribution, which NVelocity used as internal logger engine. Actually this NVelocity fork has reached version 0.5, which is the one I have included in the sample project, and whose source can be found in CastleProject's SVN repository. Revision History
|