Subtemplating with @Include

ASP.NET MVC3 includes the Razor view engine, which was the starting point for the RazorEngine project. Razor views (like their WebForm counterparts) support the ability to include partial views in the parent view. In doing so, it allows you to modularise your views into logical sections.

Much like the Razor view engine, we also support this concept in RazorEngine. We’ve implemented partial view support using the @Include methods built into TemplateBase. We specifically haven’t named them RenderPartial (ala the Razor ViewEngine) as we want to differentiate RazorEngine from it’s MVC counterpart. So how do we start subtemplating?

Here is an example template:

Here is a sample template. @Include("helloWorld")

When parsing this template, the Razor code generated creates the method calls to the TemplateBase methods. During execution, these methods will first determine if the template named “helloWorld” has been pre-compiled (and as such exists in the current TemplateService’s template cache.

We can handle the resolution of this named template two ways:

string helloWorldTemplate = "Hello World";
Razor.Compile(helloWorldTemplate, "helloWorld");

string fullTemplate = "Here is a sample template. @Include(\"helloWorld\")";
string result = Razor.Parse(fullTemplate);

In the above example, we are precompiling the template ahead of time. This enforces the template is cached (all compiled templates are named). If we don’t want to precompile the template, we need a ITemplateResolver.

Razor.AddResolver(s => GetTemplateContent(s));

string fullTemplate = "Here is a sample template. @Include(\"helloWorld\")";
string result = Razor.Parse(fullTemplate);

By adding a resolver, it allows us to dynamically locate the template which hasn’t been precompiled. This template is then compiled, executed and the result is injected into the result of the parent template. An ITemplateResolver is defined as:

public interface ITemplateResolver
{
  string GetTemplate(string name);
}

The result of the template resolver must be the unparsed template content. RazorEngine supports adding multiple template resolvers to a TemplateService, as well as declaring a template resolver though a Func<string, string> instance.

Passing Models from Parent to Child

RazorEngine also supports passing model data from a parent model to a child model using @Include<T>(templateName, model). Child models are treated in compilation the same way as parent models.

string helloWorldTemplate = "Hello @Model";
Razor.CompileWithAnonymous(helloWorldTemplate, "helloWorld");

string fullTemplate = "@Include(\"helloWorld\", @Model.Name)! Welcome to Razor!";
string result = Razor.Parse(fullTemplate, new { Name = "World" });
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)