17

I have a .NET console application that needs to generate some HTML files. I could just construct the HTML in a StringBuilder and write the contents out to a file, but I was thinking it would be nicer to use some kind of template file with placeholders for where the data goes and then process my data through it at runtime.

I'm guessing there are ways to use aspx, or T4, or some of the alternative view engines that you can use with ASP.NET MVC, but I don't know what would be easiest to integrate into a console application (or how I would go about integrating them).

I want to end up able to call something of the form:

 GenerateHtml(htmlPath, template, customDataObject);

6 Answers 6

17

One way you could do this is create a XSL file as the template, serialise your customDataObject as XML then perform a transform to generate the required HTML.

Update: Whilst I like (and do use) the string replacement method advocated by other folks here, there is a certain flexibility to using XML/XSL. Say your object has a property that is a list, for example an order object with a list of line item objects, you pretty much have to burn into your code the logic that has to render the line items.

With XSL all you do is pass the serialised order object XML to the XSL and let the XSL handle whatever HTML it needs to generate. This means you can often edit the XSL in place or have variants (order summary, detailed order etc) without adding extra code to your app with all the extra hassle of rebuild/deploy.

But then it all depends on the complexity of what you need to render, for some jobs string replacement is more obvious, for others XSL is the way. As I said, we use both.

Sign up to request clarification or add additional context in comments.

Comments

10

Here's some code that illustrates a fairly simple way to accomplish what you're trying to do:

using System;
using System.IO;

public class HtmlTemplate
{
    private string _html;

    public HtmlTemplate(string templatePath)
    {
        using (var reader = new StreamReader(templatePath))
            _html = reader.ReadToEnd();
    }

    public string Render(object values)
    {
        string output = _html;
        foreach (var p in values.GetType().GetProperties())
            output = output.Replace("[" + p.Name + "]", (p.GetValue(values, null) as string) ?? string.Empty);
        return output;
    }
}

public class Program
{
    void Main()
    {
        var template = new HtmlTemplate(@"C:\MyTemplate.txt");
        var output = template.Render(new {
            TITLE = "My Web Page",
            METAKEYWORDS = "Keyword1, Keyword2, Keyword3",
            BODY = "Body content goes here",
            ETC = "etc"
        });
        Console.WriteLine(output);
    }
}

Using this, all you have to do is create some HTML templates and fill them with replaceable tokens such as [TITLE], [METAKEYWORDS], etc. Then pass in anonymous objects that contain the values to replace the tokens with. You could also replace the value object with a dictionary or something similar.

5 Comments

this is nice, although it is lacking the ability to loop around a collection which I would need as my HTML page needs to construct a list of formatted items.
Like I said, you could use a dictionary instead of a hardcoded object; this would mean you can have a collection to loop through if you don't know at compile time what your fields are going to be.
I spent hours looking for an off-the-shelf solution, then just coded this in minutes and it worked perfectly. I'm interoperating with F#, which doesn't have such a clean constructor for an anonymous object, whereas it does for a dictionary, so the Dictionary worked better. The signature is public string Render(IDictionary dictionary).
HOWEVER! Each output = output.Replace(..) is copying the whole string, and doing one replacement, which could be expensive with a large file and many substutions. I recommend using a StringBuilder instead, so StringBuilder sb= StringBuilder(_html); ...; sb.Replace(....); return sb.ToString()
Here is a template for the code given in the answer, so that people can try it out: pastebin.com/raw/mPHDE7tQ
9

There are plenty of HTML Template engines/generators.

Just pick any depending on your needs.

Good luck.

  • https://github.com/dotliquid/dotliquid (DotLiquid is a .Net port of the popular Ruby Liquid templating language. It is a separate project that aims to retain the same template syntax as the original, while using .NET coding conventions where possible)
  • https://github.com/StubbleOrg/Stubble (Stubble trimmed down {{mustache}} templates in .NET is an implementation of the Mustache template system in C#)
  • https://github.com/scriban/scriban (Scriban is a fast, powerful, safe and lightweight scripting language and engine for .NET, which was primarily developed for text templating with a compatibility mode for parsing liquid templates)
  • https://github.com/sebastienros/fluid (Fluid is an open-source .NET template engine that is as close as possible to the Liquid template language. It's a secure template language that is also very accessible for non-programmer audiences. It also contains an ASP.NET Core MVC View Engine)
  • https://github.com/jdiamond/Nustache (Nustache - Logic-less templates for .NET)
  • https://github.com/Handlebars-Net/Handlebars.Net (Handlebars.js is an extension to the Mustache templating language created by Chris Wanstrath. Handlebars.js and Mustache are both logicless templating languages that keep the view and the code separated like we all know they should be)
  • https://github.com/Antaris/RazorEngine (RazorEngine is a templating engine built on Microsoft's Razor parsing engine, RazorEngine allows you to use Razor syntax to build dynamic templates.)

My choice was Scriban

Comments

3

As Matt mentioned, spark is nice but it could be overkill for some simple templates and gets complicated if you are not using it in MVC.

I have personally had a lot of success with NVelocity and I also publish a simple example/wrapper on using it: http://simpable.com/code/simpletemplate/

In addition, GraffitiCMS's entire theming system run on NVelocity (although I would have used spark if it were available for this task).

-Scott

4 Comments

yes I have been looking at NVelocity. it looks like the most promising solution for my problem. I am at a loss to work out where to download the "new" version that the castle project have made though.
eventually I got it working after downloading the entire castle project source and building my own NVelocity.dll. It also took a while to work out how to load my template correctly, but once I did it meets my needs perfectly. thanks
Hey Scott, it would have been nice to have at least some pointers on this page. Apparently the website is down
2

Another option instead of using XSLT as Kev suggests is to use named string formatting. Using code like this example by Phil Haack.

Here you can have your template as a string (read from a file maybe) and format it using the given object.

Now you could do something like this:

var person = new { FirstName = "rune", LastName = "grimstad" };
string template = "<html><body><h1>Hello {FirstName} {LastName}</h1></body></html>";
string html = NamedFormat(template, person);

Comments

1

There are several ways,

1- Using view engine (Razor, Spark, ...) - this is good if you are using mvc

2- Using XSLT file and transform the given xml to Html

3- Using T4 Text Templates (Best performance, easy to understand)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.