Using the RazorFolderHostContainer Class

RazorFolderHostContainer can be used a file folder that maps templates to the file system. This works much in the same way that ASP.NET MVC uses templates as views. However, it's important to understand that the behavior is not the same as ASP.NET MVC. For example, there's no automatic View discovery, nor do Views have to be located in a Views folder.

The container works by letting you provide virtual file paths ("/template.cshtml" or "/folder/template.cshtml") to a template that is then rendered. Templates can reference other Partial templates and templates can use a Layout page, much in the same way that MVC uses these features. Just remember that all related templates must be referenced with their full virtual path ("~/template.cshtml").

Running the Folder Host Container

To run folder host templates looks like this:

var host = new RazorFolderHostContainer();

host.TemplatePath = Path.GetFullPath(@"..\..\FileTemplates\");
host.BaseBinaryFolder = Environment.CurrentDirectory;

// add model assembly - ie. this assembly
host.AddAssemblyFromType(typeof(Person));

host.UseAppDomain = true;
//host.Configuration.CompileToMemory = true;
//host.Configuration.TempAssemblyPath = Environment.CurrentDirectory;

host.Start();

Person person = new Person()
{
    Name = "Rick",
    Company = "West Wind",
    Entered = DateTime.Now,
    Address = new Address()
    {
        Street = "32 Kaiea",
        City = "Paia"
    }
};

string result = host.RenderTemplate("~/HelloWorld.cshtml", person);

Console.WriteLine(result);
Console.WriteLine("---");
Console.WriteLine(host.Engine.LastGeneratedCode);

host.Stop();


if (result == null)
    Assert.Fail(host.ErrorMessage);

Assert.IsTrue(result.Contains("West Wind"));

where the template might look like this:

@model RazorHostingTests.Person
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>    
    @RenderPartial("~/Header_Partial.cshtml",Model)

    @Model.Name @Model.Company @Model.Address.City @Model.Entered 

    @{for (int i = 0; i < 10; i++)
      {
          Response.WriteLine(i + ".");
      }  

   You can also render nested templates from string
   @RenderTemplate("Child Template rendered from String. Name: @Model.Name",Model) 
</body>
</html>

Generally you will instantiate a host container once in your application and then store it somewhere globally for reuse only shutting down when the application shuts down. You can run many RenderTemplate() requests agains the single Host instance in this example.

If the template was previously compiled and the timestamp hasn't changed the template is run from the pre-compiled assembly. If the template has not been compiled or

Running in a separate AppDomain with UseAppDomain

Note that you can choose to host the container in a separate AppDomain by using:

host.UseAppDomain = true;

If you do, make sure any models passed to the host for rendering are marked serializable or inherit from MarshalByRefObject. Using an AppDomain is useful when loading lots of templates and allows for unloading the engine to reduce memory usage. It also helps isolate template code from the rest of your application for security purposes, since Razor templates essentially can execute any code in the context of the host.


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