Skip to content
  • English Deutsch

benjamin-abt.com

Performance is a feature | Cloud - AI - Azure - .NET - Sustainability

  • Home
  • Blog
  • Portfolio
    • Overview
    • Workshops & Training
    • Publications
  • Contact
  • Home
  • Blog

Header and Footer Layouts with Handlebars.NET

Header and Footer Layouts with Handlebars.NET
January 21, 2024 3 min read BEN ABT
ASP.NET Core .NET Csharp

One of the last blog posts (Text and EMail Templates with Handlebars.NET ) was generally about HandleBars.NET - a very popular template engine. This post is about how you can easily implement layouts with Handlebars.

The snippet in the previous post was as follows:

C#
 1// MyTemplateProvider.cs
 2
 3    public MyTemplateProvider()
 4    {
 5        _handlebars = Handlebars.Create();
 6
 7        Init(); // Add this
 8    }
 9
10    private void Init()
11    {
12        // Add Header Template
13        _handlebars.RegisterTemplate("Header_Template", @"<strong>MyCompany - {{Title}}</strong>");
14
15        // Add Footer Template
16        _handlebars.RegisterTemplate("Footer_Template", @"<i>MyCompany - Copyright 2023</i>");
17
18        // Register Welcome Mail
19        _handlebars.RegisterTemplate("WelcomeMail_Template",
20            """
21            <div>
22                <h1>{{>Header_Template}}</h1>
23                <div class="body">
24                    <h3>Welcome to our demo {{UserName}}!</h3>
25                <p>Thank you for registering. Have fun!</p>
26                </div>
27                <footer>{{>Footer_Template}}</footer>
28            </div>
29            """);
30   }

As you can see, a template is registered that references other templates - but explicitly. I therefore have to take care of the frame - in this case the header and footer - for my actual content myself. This is not nice and represents a redundancy.

Partial Blocks

Handlebars supports a functionality called Partial Blocks. While simple Partials represent a content block, partial blocks are the construct around it. In Razor, this is comparable to sections. Partial blocks can therefore be used to represent the surrounding content - like our layouts.

C#
1_handlebars.RegisterTemplate("MailLayout", """
2    <div>
3        <h1><strong>MyCompany - {{Title}}</strong></h1>
4        <div class="body">
5            {{> content}}
6        </div>
7        <footer><i>MyCompany - Copyright {{On.Year}}</i></footer>
8    </div>
9    """);

Partial blocks are also registered as templates, but have the special feature that they contain the reserved partial keyword content. This is then replaced by the actual content you have in your template.

The layout can then be referenced in the actual template by specifying the partial block:

C#
1_handlebars.RegisterTemplate("WelcomeMail_Template",
2    """{{#> MailLayout}}
3            <h3>Welcome to our demo {{UserName}}!</h3>
4            <p>Thank you for registering. Have fun!</p>
5       {{/MailLayout}}
6    """);

Full Sample

C#
 1using HandlebarsDotNet;
 2
 3namespace BenjaminAbt.Samples.HandlebarsNET;
 4
 5internal class Program
 6{
 7    static void Main(string[] args)
 8    {
 9        MyTemplateProvider templateProvider = new();
10
11        List<string> userNames = ["Batman", "Robin"];
12        foreach (var userName in userNames)
13        {
14            string text = templateProvider.RenderWelcomeMail(userName);
15
16            Console.WriteLine($"To: {userName}");
17            Console.WriteLine(text);
18            Console.WriteLine("-------------------");
19        }
20    }
21}
22
23// MyTemplateProvider.cs
24public class MyTemplateProvider
25{
26    private readonly IHandlebars _handlebars;
27
28    public MyTemplateProvider()
29    {
30        _handlebars = Handlebars.Create();
31
32        Init(); // Add this
33    }
34
35    private void Init()
36    {
37
38        _handlebars.RegisterTemplate("MailLayout", """
39            <div>
40                <h1><strong>MyCompany - {{Title}}</strong></h1>
41                <div class="body">
42                    {{> content}}
43                </div>
44                <footer><i>MyCompany - Copyright {{On.Year}}</i></footer>
45            </div>
46            """);
47
48        // Register Welcome Mail
49        _handlebars.RegisterTemplate("WelcomeMail_Template", InternalRegisterTemplateWithLayout(
50            """
51                <h3>Welcome to our demo {{UserName}}!</h3>
52                <p>Thank you for registering. Have fun!</p>
53            """));
54    }
55
56    private string InternalRegisterTemplateWithLayout(string template)
57        => "{{#> MailLayout}}" + template + "{{/MailLayout}}";
58
59    private HandlebarsTemplate<object, object>? _welcomeTemplate = null;
60    public string RenderWelcomeMail(string userName)
61    {
62        _welcomeTemplate ??= _handlebars.Compile("{{> WelcomeMail_Template}}");
63
64        var data = new
65        {
66            Title = "Welcome!",
67            UserName = userName,
68            On = DateTimeOffset.UtcNow
69        };
70
71        var text = _welcomeTemplate(data);
72        return text;
73    }
74}

Have fun!

Related articles

Problem Details in ASP.NET Core and .NET 11

Oct 5, 2026 - 12 min read

Problem Details in ASP.NET Core and .NET 11

builder.Services.AddProblemDetails() registers infrastructure. It does not create an error contract. An ASP.NET Core request can fail during …

Resilience in .NET with Microsoft.Extensions.Resilience

Sep 21, 2026 - 11 min read

Resilience in .NET with Microsoft.Extensions.Resilience

Retries are the most visible resilience strategy and the easiest one to misuse. Repeating a failing call can recover from a short network …

What Matters in ASP.NET Core 11

Sep 14, 2026 - 10 min read

What Matters in ASP.NET Core 11

ASP.NET Core 11 has no single feature that fundamentally changes how web applications are built. That is not a criticism. Mature frameworks …


BEN ABT

BEN ABT

Ben is Chief Engineering Officer and Principal Software Engineer at Medialesson.de, with a strong focus on .NET and Microsoft Azure. In his professional role, he designs and builds highly scalable platforms for hybrid and cloud-based scenarios. He also advises companies and C-levels on migrating to the sovereign cloud.

He runs myCSharp.de, the largest and most active German-speaking C# community forum, actively contributes to both his own and external open-source projects and regularly shares his knowledge through his blog, at community events, conferences and as a writer for technical magazines.

Let's Work Together

Looking for an experienced Platform Architect or Engineer for your next project? Whether it's cloud migration, platform modernization or building new solutions from scratch - I'm here to help you succeed.

New Platforms

Modernization

Training & Consulting

Contact Me
X Facebook LinkedIn WhatsApp
Back Next Blog Post

Open for work!

Contact Me
BEN ABT BEN ABT Software Engineer · Microsoft MVP Passionate about .NET, Azure, performance optimization and sustainable software engineering.

Medialesson GmbH Logo

Microsoft MVP Logo

Recent posts

View all
Stop Using nginx as Your Default Static File Server in Docker

Stop Using nginx as Your Default Static File Server in …

Oct 24, 2026
Containerizing .NET in 2026 Without a Dockerfile

Containerizing .NET in 2026 Without a Dockerfile

Oct 20, 2026
Problem Details in ASP.NET Core and .NET 11

Problem Details in ASP.NET Core and .NET 11

Oct 5, 2026
Resilience in .NET with Microsoft.Extensions.Resilience

Resilience in .NET with Microsoft.Extensions.Resilience

Sep 21, 2026
What Matters in ASP.NET Core 11

What Matters in ASP.NET Core 11

Sep 14, 2026

Tags

.NET (192) Csharp (96) ASP.NET Core (48) Azure (41) DevOps (17) Docker (14) Microsoft (14) EF Core (11) Microsoft MVP (11) AI (10) GitHub (10) GitHub Copilot (10) ASP.NET (9) Security (9) Synology (9) Architecture (8) Raspberry (8) Azure Functions (7) Cloudflare (7) Bicep (6)
benjamin-abt.com

About BEN

Benjamin Abt is a Software Engineer, Platform Architect and Microsoft MVP specializing in .NET, Azure, cloud architecture, performance optimization and sustainable software development.

Connect

  • Follow me on GitHub
  • Follow me on LinkedIn
  • Follow me on Mastodon
  • Microsoft MVP profile
  • Follow SchwabenCode on GitHub
  • Follow me on X

Quick Links

  • Portfolio
  • Blog
  • Workshops & Training
  • Publications
  • Get in Touch
  • Sitemap
Open for Work

© Copyright Benjamin Abt & SchwabenCode | 2011 - 2026

Content licensed under CC BY 4.0 unless otherwise noted.

  • Impressum
  • Privacy
  • Contact