Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RazorEngine layouts

Tags:

c#

razorengine

I am using the Razor engine https://github.com/Antaris/RazorEngine to parse the body of my email templates. Is it possible to define a layout and include other .cshtml files? for example a common header and a footer.

like image 939
ministrymason Avatar asked Jul 10 '12 13:07

ministrymason


2 Answers

I got common templates and a layout working, with the help of these two posts:

RazorEngine string layouts and sections?

http://blogs.msdn.com/b/hongyes/archive/2012/03/12/using-razor-template-engine-in-web-api-self-host-application.aspx

This is my solution:

Solution 1: Layout

Used by setting _Layout

@{     _Layout = "Layout.cshtml";     ViewBag.Title = Model.Title;  } 

Footer

@section Footer  {    @RenderPart("Footer.cshtml") } 

Layout.cshtml

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html>     <head>     </head>     <body>         <div id="content">             @RenderBody()         </div>          @if (IsSectionDefined("Footer"))         {              <div id="footer">                 @RenderSection("Footer")             </div>         }     </body>  </html> 

TemplateBaseExtensions

Extend TemplateBase with a RenderPart Method

public abstract class TemplateBaseExtensions<T> : TemplateBase<T> {     public string RenderPart(string templateName, object model = null)     {         string path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Templates", templateName);         return Razor.Parse(File.ReadAllText(path), model);     } } 

Razor Config

Set BaseTemplateType to your TemplateBaseExtensions class

TemplateServiceConfiguration templateConfig = new TemplateServiceConfiguration {      BaseTemplateType = typeof(TemplateBaseExtensions<>) };  Razor.SetTemplateService(new TemplateService(templateConfig)); 

Edit Solution 2:

If you are using a TemplateResolver. RenderPart isn't needed use the @Include instead

Footer

@section Footer  {    @Include("Footer.cshtml") } 

Resolver

public class TemplateResolver : ITemplateResolver {     public string Resolve(string name)     {         if (name == null)         {             throw new ArgumentNullException("name");         }          string path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Templates", name);         return File.ReadAllText(path, System.Text.Encoding.Default);     } } 

Config

TemplateServiceConfiguration templateConfig = new TemplateServiceConfiguration {      Resolver = new TemplateResolver() }; Razor.SetTemplateService(new TemplateService(templateConfig)); 

Update by The Muffin Man Specify a template and render a string

var templateResolver = Razor.Resolve("Registration.cshtml"); return templateResolver.Run(new ExecuteContext()); 

Also I, along with others at this link https://github.com/Antaris/RazorEngine/issues/61 had issues with using _Layout whereas Layout worked.

'_Layout' is the old syntax. It was updated to 'Layout' in a future release.

like image 78
ministrymason Avatar answered Oct 05 '22 12:10

ministrymason


You can easily do a lot of stuff with Razor; however, that particular project seems to abstract away a lot of the Razor engine stuff you could do (which is both good and bad). In your situation, it sounds like you would be much better off implementing your own Razor solution (it's actually not that bad) and then you can have your templates throw exceptions or pull in other content pretty easily.

For example; rolling your own solution allows you to make a base class for your razor templates which can expose the capacity to pull in "partial views" by invoking other templates. In addition, you can do model checking and throw exceptions if certain properties are null.

like image 42
Tejs Avatar answered Oct 05 '22 13:10

Tejs