April 23, 2012

Localizable text template engine using StringTemplate 4

In the previous post I shown how to create localizable text template engine using RazorEngine.
I suggest to use the RazorEngine in any case.
But there is an one case where RazorEngine can not help you. It will happened if you try to use RazorEngine in dynamically loaded assembly.
There is a simple example. Your system can load the plugins dynamically. One of your plugin have to use text template engine to parse the strings. In that case RazorEngine will throw an error with the message:

Precondition failed: templateType != null

It's known issue and if you interested in it you can find a detailed description of this problem here.

In that case, you have to use something else for a template engine and I suggest to use StringTemplate to avoid that kind of problems.

In this post I will show you how to use StringTemplate engine.

Using the StringTemplate engine

The following command in the Package Manager console will install StringTemplate 4 package into your ASP.NET MVC 4 WebAPI application:

PM > Install-Package Antlr4.StringTemplate

StringTemplate is a template engine library used for generating text from data structures. StringTemplate's distinguishing characteristic is that it strictly enforces model-view separation unlike other comparable template engines. It is particularly good at multi-targeted code generators, multiple site skins, and internationalization/localization.

So, it fully meets our needs.

In my previous post I shown how to write and use the localizable template service.

So, here I will talk only about another realization of the interface ITemplateEngine for StringTemplate, because everything else will stay the same.

I would like to remind you how the ITemplateEngine interface looks:

    public interface ITemplateEngine
        string Parse(string template, dynamic model);

And there is the realization of this interface for StringTemplate engine:

    public class StringTemplateEngine : ITemplateEngine
        public string Parse(string template, dynamic model)
            var group = new TemplateGroupString("group", "delimiters \"$\", \"$\"");

            var renderer = new AdvancedRenderer();
            group.RegisterRenderer(typeof(DateTime), renderer);
            group.RegisterRenderer(typeof(double), renderer);

            group.DefineTemplate("template", template, new[] { "Model" });

            var stringTemplate = group.GetInstanceOf("template");
            stringTemplate.Add("Model", model);

            return stringTemplate.Render();

It is a little bit complicated example and I will explain you why.
The first line just creates a template group with specified delimiters '$' (default delimiters are '<' and '>').
The next three lines help us to specify the renderer for the types DateTime and double. I have to use custom renderer to allow formatting my DateTime and double values, and that is only one reason why I use the template group instead of specify only one template.
The next line creates new template in the template group with the name 'template' and use the template text for a content of the template.
Then I take this template from a group and add my model to template.
At last, just call Render method of the template and return result back.

To make formatting inside the template possible I use custom renderer for StringTemplate called AdvancedRenderer:

    public class AdvancedRenderer : IAttributeRenderer
        public string ToString(object obj, string formatString, System.Globalization.CultureInfo culture)
            if (obj == null)
                return null;

            if (string.IsNullOrEmpty(formatString))
                return obj.ToString();

            return string.Format("{0:" + formatString + "}", obj);

It is really simple but powerful renderer. I will show you how to use the formatting directly in the template later.

So, I have done with the template engine. And we can start using it already.

In the last part of the post, I would like to share the example of template that would be easier to understand the syntax of StringTemplate.

Using the localizable template service

To demonstrate how to use this service let's create the template file first.
Create a directory 'Templates' in your project.
Then click the right mouse button on this directory in the 'Solution Explorer' and select 'Add' -> 'New Item...' (or just press Ctrl+Shift+A).
In the new window click on 'Visual C# Items' and select the 'Text File' in the list. Enter the file name - 'first.template' and click 'Add' button.

Then insert the next text into template file:

ID: $Model.Id$
CreatedDate: $Model.CreatedDate; format="dd.MM.yyyy HH:mm"$
Name: $Model.Name$
Price: $Model.Price; format="0.00"$
$Model.Items:{item |
    item $i$ - $item.Key$  $if(item.Value)$enabled$else$-$endif$

Then write some simple code to prepare the data model and to parse the template:

            var model = new { 
                Id = 10,
                CreatedDate = DateTime.Now,
                Name = "Name1",
                Price = 123.45356,
                Items = new List<KeyValuePair<string, bool>> {
                    new KeyValuePair<string, bool>("Item1", false),
                    new KeyValuePair<string, bool>("Item2", true),
                    new KeyValuePair<string, bool>("Item3", false),
                    new KeyValuePair<string, bool>("Item4", false),
                    new KeyValuePair<string, bool>("Item5", true)

            var templateService = new TemplatesService(new FileSystemService(), new StringTemplateEngine());

            var result = templateService.Parse("first", model);

You can find detailed information about TemplateService and FileSystemService in my previous post how to create localizable text template engine using RazorEngine.

After that, put the break point after the last line (var result = ...) and run your application in Debug mode.
When the debugger stops on that break point just check the value of the result variable in the Text Visualizer.

If should contains the next text:

ID: 10
CreatedDate: 23.04.2012 15:54
Name: Name1
Price: 123.45
    item 1 - Item1  -
    item 2 - Item2  enabled
    item 3 - Item3  -
    item 4 - Item4  -
    item 5 - Item5  enabled

So, as you can see our renderer (AdvancedRenderer) allows us to specify string for formatting as we use usually for string.Format() method.

That's all.
Good luck.


  1. Which methons do you personally use to search for information for your future posts and which exact search websites or techniques do you generally rely on?

    1. I don't use any search methods. I'm just trying to cover the topics which I'm working on.

  2. very informative article.And very well explained about different protocols.keep posting like good content posts.

    Oracle Fusion Cloud HCM Online Training

  3. Big Data and Hadoop is an ecosystem of open source components that fundamentally changes the way enterprises store, process, and analyze data.
    hadoop training in bangalore

  4. Harvard Business Review named data scientist the "sexiest job of the 21st century".This Data Science course will cover the whole data life cycle ranging from Data Acquisition and Data Storage using R-Hadoop concepts, Applying modelling through R programming using Machine learning algorithms and illustrate impeccable Data Visualization by leveraging on 'R' capabilities.With companies across industries striving to bring their research and analysis (R&A) departments up to speed, the demand for qualified data scientists is rising.

    data science training in bangalore

  5. myTectra Amazon Web Services (AWS) certification training helps you to gain real time hands on experience on AWS. myTectra offers AWS training in Bangalore using classroom and AWS Online Training globally. AWS Training at myTectra delivered by the experienced professional who has atleast 4 years of relavent AWS experince and overall 8-15 years of IT experience. myTectra Offers AWS Training since 2013 and retained the positions of Top AWS Training Company in Bangalore and India.

    aws training in bangalore

  6. IOT Training in Bangalore - Live Online & Classroom
    Iot Training course observes iot as the platform for networking of different devices on the internet and their inter related communication. Iot Training in Bangalore

  7. Gaining Python certifications will validate your skills and advance your career.
    python certification

  8. Devops is not a Tool.Devops Is a Practice, Methodology, Culture or process used in an Organization or Company for fast collaboration, integration and communication between Development and Operational Teams. In order to increase, automate the speed of productivity and delivery with reliability.

    python training in bangalore
    aws training in bangalore
    artificial intelligence training in bangalore
    data science training in bangalore
    machine learning training in bangalore
    hadoop training in bangalore
    devops training in bangalore

  9. JavaScript is the most widely deployed language in the world
    Javascript Interview Questions