66

Some time ago rendering a template using RazorEngine was as easy as:

string s = RazorEngine.Razor.Parse()

However, for some reason, its authors changed their minds about the API and now the simplest way to render a template is:

var key = new RazorEngine.Templating.NameOnlyTemplateKey("EmailTemplate", RazorEngine.Templating.ResolveType.Global, null);
RazorEngine.Engine.Razor.AddTemplate(key, new RazorEngine.Templating.LoadedTemplateSource("Ala ma kota"));
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
RazorEngine.Engine.Razor.RunCompile(key, sw);
string s = sb.ToString();

(At least this is what I deduced from the new API. The old one is marked as deprecated.)

Is there a way to use the new API to render a template without caching, keys, and other fancy stuff? All of the official examples simply don't work.

ruffin
  • 16,507
  • 9
  • 88
  • 138
Spook
  • 25,318
  • 18
  • 90
  • 167
  • 12
    I second that opinion. The examples are useless and I couldn't just use the deprecated methods because now the method RazorEngine.Templating.RazorEngineService.GetCompiledTemplate keeps giving me the error "No template exists with key..." The upgrade is far too complicated and painful : why are we supposed to use a cache and a template key ? I've forked the project and am trying to get my old code to work with the new version... – JJP Feb 19 '15 at 14:42
  • 4
    Make sure to put: "using RazorEngine;" and "using RazorEngine.Templating;" at the top, otherwise the examples won't work. – ooXei1sh Apr 01 '15 at 18:28

4 Answers4

82

Well, after searching the code, I found some useful examples (https://github.com/Antaris/RazorEngine/blob/master/src/source/RazorEngine.Hosts.Console/Program.cs) and found out that if you include

using RazorEngine.Templating;

at the top of your class, you can use some extension methods (https://github.com/Antaris/RazorEngine/blob/master/src/source/RazorEngine.Core/Templating/RazorEngineServiceExtensions.cs) that will help you.

Painless template compilation :

Engine.Razor.Compile(templatePath, "templateNameInTheCache", modelType);

Template Parsing :

Engine.Razor.Run("templateNameInTheCache", modelType, model);

And now you can do both at the same time !

string myParsedTemplate = Engine.Razor.RunCompile(templatePath, "templateNameInTheCache", null, model)

Which is the equivalent of doing this

Engine.Razor.AddTemplate("templateNameInTheCache", TemplateLoader.GetTemplate(templatePath));
Engine.Razor.Compile("templateNameInTheCache", modelType);
string finallyThisIsMyParsedTemplate = Engine.Razor.Run("templateNameInTheCache", modelType);

Please note that I'm currently testing this, but it seems to work fine.

JJP
  • 1,439
  • 17
  • 21
  • 7
    Any idea how to remove the compiled template from cache afterwards? – JTW Jun 29 '15 at 02:06
  • It seems you have to create a new instance of the Cache Provider, see this link : http://stackoverflow.com/questions/14369614/razorengine-un-cache-compiled-templates – JJP Jun 29 '15 at 07:37
  • 4
    I cannot find TemplateLoader – bublegumm Aug 16 '15 at 14:57
  • 4
    @JJP Are you sure `Engine.Razor.Compile(templatePath, "templateNameInTheCache", modelType); ` works? Looking through their code it appears that the method expects the template string and not path to the template. The code you provided didn't work for me as is, it gave me the resolved server path as template. Thanks. – Justin Sep 10 '15 at 13:30
  • 4
    @Justin, dont' forget to use File.ReadAllText(HostingEnvironment.MapPath("YourView.cshtml")) – Dominique Alexandre Sep 24 '15 at 17:52
  • Does RunCompile check if it is in cache first or do we have to do this manual check? bool isCached = RazorEngine.Engine.Razor.IsTemplateCached(emailTypeKey, typeof(T)); string result = string.Empty; if (isCached) { result = RazorEngine.Engine.Razor.Run(emailTypeKey, typeof(T), model, null); } else { result = RazorEngine.Engine.Razor.RunCompile(content, emailTypeKey, typeof(T), model); } – David Sep 30 '15 at 16:38
  • Yes, the Engine checks the cache first, if the file is not in cache it is cached and then compiled. ref : https://github.com/Antaris/RazorEngine/blob/817fbfbb8264845a78458c110e38125555e0ddf2/src/source/RazorEngine.Core/Templating/RazorEngineService.cs – JJP Oct 04 '15 at 13:57
  • 1
    @Dominique Alexandre I figured that out. I guess I was getting misguided by the variable name "templatePath". – Justin Nov 05 '15 at 20:10
  • Has this changed again? I can't seem to figure out what it wants now. It wants RunCompile(TemplateKey, TextWriter, ModelType, Model, DynamicViewBag). Can someone update this answer? – Smeiff Jul 05 '16 at 21:02
  • @Smeiff This is a little late, but just in case someone else is experiencing the same issue, you have to add the namespace RazorEngine.Templating to your using statements. – user2023116 Nov 08 '16 at 16:26
  • 3
    @user2023116 Thanks for the help. It is a shame you need to dig this deep to piece together a working example. Big thumbs down for such breaking changes in this library – nachonachoman Jan 17 '17 at 18:21
  • 1
    Agreed @user2023116 - I may revert my upgrade and stick with the older version, or look for an alternative. Razor.Parse is *the* function 90% of users will need, and it's made hard to find and use. – Quango May 22 '17 at 09:43
  • @JTWolgamott can you please tell me what you used. – coder771 Mar 26 '18 at 07:54
  • @coder771 I’m now using Python 3 and the Jinja2 templating engine. Works quite nicely! – JTW Mar 26 '18 at 10:44
  • 3
    why are they forcing us to use their cache implementation? If I wanted to cache the rendered templates I could implement that myself. Please just give us the `Parse` method back – jtate Jul 18 '18 at 21:54
7

The following code works for ResolvePathTemplateManager (October, 2017):

var templateManager = new ResolvePathTemplateManager(new[] { rootPath });

var config = new TemplateServiceConfiguration
{
    TemplateManager = templateManager
};

Engine.Razor = RazorEngineService.Create(config);

// ...

var html = Engine.Razor.RunCompile("Test.cshtml", null, model);

Source: in RazorEngineServiceTestFixture.cs, look for ResolvePathTemplateManager.

turdus-merula
  • 8,546
  • 8
  • 38
  • 50
1

Building on @turdus-merula's answer, I wanted the temp files to be cleaned up when the default AppDomain is unloaded. I disabled the temp file locking in the config, which allows the temp folder to be deleted.

var config = new TemplateServiceConfiguration
{
    TemplateManager = new ResolvePathTemplateManager(new[] {"EmailTemplates"}),
    DisableTempFileLocking = true
};

Engine.Razor = RazorEngineService.Create(config);

var html = Engine.Razor.RunCompile("Test.cshtml", null, model);
Connor
  • 807
  • 1
  • 10
  • 20
1

Just FYI, using the RazorEngine API leads to memory leak. There is an official issue reported, that compiling templates keeps generating temp files that are very hard to get rid of. So be very careful if you use this in production.

Last I used this, it kept adding +1MB to memory on every template compilation, even when using cached templates!

stann1
  • 576
  • 3
  • 11