Maintainer strongly believes implementing @include
and @Layout
is unnecessary complexity for standalone RazorEngine.
Since RazorEngine.Compile accept template as a string, one will need also to accept a Dictionary (key, template)
to be able to resolve @Include
and @Layout
It is easily implementable outside of RazorEngine
We would like to have code like this: Supply primary template
, parts
, and model
and see the result as a string
namespace ConsoleApp11 { class Program { static void Main(string[] args) { string template = @" @{ Layout = ""MyLayout""; } <h1>@Model.Title</h1> @Include(""outer"", Model) "; IDictionary<string, string> parts = new Dictionary<string, string>() { {"MyLayout", @" LAYOUT HEADER @RenderBody() LAYOUT FOOTER "}, {"outer", "This is Outer include, <@Model.Title>, @Include(\"inner\")"}, {"inner", "This is Inner include"} }; IRazorEngine razorEngine = new RazorEngine(); MyCompiledTemplate compiledTemplate = razorEngine.Compile(template, parts); string result = compiledTemplate.Run(new {Title = "Hello"}); Console.WriteLine(result); Console.ReadKey(); } } }
Output
LAYOUT HEADER <h1>Hello</h1> This is Outer include, <Hello>, This is Inner include LAYOUT FOOTER
Lets make custom template base with Include
function. It will be available as @Include("footer")
in template. We will inialize IncludeCallback
just before running template
public class MyTemplateBase : RazorEngineTemplateBase { public Func<string, object, string> IncludeCallback { get; set; } public Func<string> RenderBodyCallback { get; set; } public string Layout { get; set; } public string Include(string key, object model = null) { return this.IncludeCallback(key, model); } public string RenderBody() { return this.RenderBodyCallback(); } }
public static class RazorEngineCoreExtensions { public static MyCompiledTemplate Compile(this RazorEngine razorEngine, string template, IDictionary<string, string> parts) { return new MyCompiledTemplate( razorEngine.Compile<MyTemplateBase>(template), parts.ToDictionary( k => k.Key, v => razorEngine.Compile<MyTemplateBase>(v.Value))); } }
public class MyCompiledTemplate { private readonly IRazorEngineCompiledTemplate<MyTemplateBase> compiledTemplate; private readonly Dictionary<string, IRazorEngineCompiledTemplate<MyTemplateBase>> compiledParts; public MyCompiledTemplate(IRazorEngineCompiledTemplate<MyTemplateBase> compiledTemplate, Dictionary<string, IRazorEngineCompiledTemplate<MyTemplateBase>> compiledParts) { this.compiledTemplate = compiledTemplate; this.compiledParts = compiledParts; } public string Run(object model) { return this.Run(this.compiledTemplate, model); } public string Run(IRazorEngineCompiledTemplate<MyTemplateBase> template, object model) { MyTemplateBase templateReference = null; string result = template.Run(instance => { if (!(model is AnonymousTypeWrapper)) { model = new AnonymousTypeWrapper(model); } instance.Model = model; instance.IncludeCallback = (key, includeModel) => this.Run(this.compiledParts[key], includeModel); templateReference = instance; }); if (templateReference.Layout == null) { return result; } return this.compiledParts[templateReference.Layout].Run(instance => { if (!(model is AnonymousTypeWrapper)) { model = new AnonymousTypeWrapper(model); } instance.Model = model; instance.IncludeCallback = (key, includeModel) => this.Run(this.compiledParts[key], includeModel); instance.RenderBodyCallback = () => result; }); } public void Save() { /* TODO this.compiledTemplate.SaveToFile(); this.compiledTemplate.SaveToStream(); foreach (var compiledPart in this.compiledParts) { compiledPart.Value.SaveToFile(); compiledPart.Value.SaveToStream(); } */ } public void Load() { // TODO } }
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4