Keeping HostContainers Alive and Running

A key feature of HostContainers is that they cache the generated assemblies for each template, so that you don't have to recompile templates each time. As you might expect, template compilation is expensive and slow and creates a new assembly that can never be unloaded during the lifetime of the AppDomain.

This is easy to do with a small application specific wrapper class described at the end of this topic.

Caching the Host Container in a Static or Singleton

The easiest way to cache a host container is via static variable declared in a relevant location of your application.

For example you can do this:

public class AppUtils 
{
    public static RazorFolderHostContainer RazorHost { get; set; }
    ...
}

and then to use it:

RazorFolderHostContainer host;

if (AppUtils.RazorHost == null)
{
    var host = new RazorFolderHostContainer();
    // ... set up the host
    AppUtils.RazorHost = host;
}

AppUtils.RenderTemplate("~/topic.cshtml",topic);

Put it all together: Application Integration

I like to wrap all template rendering logic into an application specific static class so I cache the host container and not have to worry about loading the container.

Here's what this small class looks like:

public class AppTemplates
{
    public static RazorFolderHostContainer RazorHost { get; set; }
    
    public static string RenderTemplate(string template, object model, out error)
    {
        if (RazorHost == null)
            StartRazorHost();        
        
        string result = RazorHost.RenderTemplate(template,model);
        if (result == null)
            error = RazorHost.ErrorMessage;
            
        return result;
    }
    
    public static void StartRazorHost()
    {
        var host = new RazorFolderHostContainer() 
        {
            // *** Set your Folder Path here - physical or relative ***
            TemplatePath = Path.GetFullPath(@".\templates\"),
            BaseBinaryFolder = Environment.CurrentDirectory
        };
        
        // Add any assemblies that are referenced in your templates
        host.AddAssemblyFromType(typeof(Person));
        host.AddAssemblyFromType(this.GetType());
  
        // Always must start the host
        host.Start();
        
        RazorHost = host;
    }
    
    public static void StopRazorHost()
    {
        RazorHost?.Stop();
    }
}

This consolidates all the logic needed to load, shut down and render templates using the RazorHost. This reduces the code to render a template to a single line of code now:

AppTemplates.RenderTemplate("~/header.cshtml",topic);

This method will start the host if it's not loaded and then go ahead and render the template.


© West Wind Technologies, 2018 • Updated: 05/29/17
Comment or report problem with topic