TemplateBuilder.Core 2.0.0

dotnet add package TemplateBuilder.Core --version 2.0.0
                    
NuGet\Install-Package TemplateBuilder.Core -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TemplateBuilder.Core" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TemplateBuilder.Core" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="TemplateBuilder.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TemplateBuilder.Core --version 2.0.0
                    
#r "nuget: TemplateBuilder.Core, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TemplateBuilder.Core@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TemplateBuilder.Core&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=TemplateBuilder.Core&version=2.0.0
                    
Install as a Cake Tool

TemplateBuilder.Core

Current version: 2.0.0

Render Scriban-powered HTML templates to strings in any .NET 10 application. Lightweight, no UI — just service registration and injection.

To create and manage templates, install the companion package TemplateBuilder.Editor.


Requirements

  • .NET 10
  • SQL Server

Quick Start

1. Install

dotnet add package TemplateBuilder.Core --version 2.0.0

2. Add a connection string

// appsettings.json
{
  "ConnectionStrings": {
    "TemplateDb": "Server=.;Database=TemplateBuilder;Trusted_Connection=True;TrustServerCertificate=True;"
  }
}

3. Register in Program.cs

using TemplateBuilder.Core.Extensions;

builder.Services.AddTemplateBuilder(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString("TemplateDb")!;
});

4. Inject and render

using TemplateBuilder.Domain.Interfaces;

public class EmailService(ITemplateEngine engine)
{
    // Render by template name (as entered in the editor UI)
    public Task<string> RenderByNameAsync(string name, object model, CancellationToken ct = default)
        => engine.RenderByNameAsync(name, model, ct);

    // Render by template database ID
    public Task<string> RenderByIdAsync(int id, object model, CancellationToken ct = default)
        => engine.RenderAsync(id, model, ct);
}

API Reference

AddTemplateBuilder(options)

Registers all TemplateBuilder services. Call once in Program.cs.

Option Default Description
ConnectionString (required) SQL Server connection string
EnableCaching true Cache rendered template bodies in memory
CacheDurationMinutes 60 How long to cache a template version

ITemplateEngine

The primary rendering interface. Inject into any service or controller.

// Render a template by its database ID
Task<string> RenderAsync(int templateId, object model, CancellationToken ct = default);

// Render a template by its name (must be active)
Task<string> RenderByNameAsync(string templateName, object model, CancellationToken ct = default);

// Render an arbitrary Scriban body string directly (no DB lookup)
Task<string> RenderBodyAsync(string body, object model, CancellationToken ct = default);

RenderAsync / RenderByNameAsync serve the last Active version of the template — its highest-numbered version with IsActive = true — skipping any newer Draft version saved via the Editor's Save Draft button. As of 2.0.0, three typed exceptions (TemplateBuilder.Domain.Exceptions) can be thrown:

Exception Thrown when
TemplateNotFoundException No template with that ID/name exists
TemplateInactiveException The template itself is deactivated (Template.IsActive == false)
NoActiveVersionException The template is active but every saved version is a Draft — nothing Active to render

Breaking change from 1.x: an inactive template previously threw TemplateNotFoundException; it now throws the more specific TemplateInactiveException.

ITemplateRepository

Direct access to template data.

Task<Template?> GetByIdAsync(int id, CancellationToken ct = default);
Task<Template?> GetByNameAsync(string name, CancellationToken ct = default);
Task<IReadOnlyList<Template>> GetAllAsync(CancellationToken ct = default);
Task<IReadOnlyList<TemplateVersion>> GetVersionHistoryAsync(int templateId, CancellationToken ct = default);

Template Syntax

Templates use Scriban. Model properties are accessed via model.*:

<p>Hello <strong>{{ model.FirstName }}</strong>,</p>

{{ for item in model.Items }}
  <p>{{ item.Name }} — {{ item.Price | math.format "C" }}</p>
{{ end }}

{{ if model.IsPremium }}
  <p>Thank you for being a premium member.</p>
{{ end }}

Model property lookup is case-insensitive{{ model.firstname }} and {{ model.FirstName }} resolve to the same value.


Example: Sending a Rendered Email

public class InvoiceEmailSender(ITemplateEngine engine, IEmailClient emailClient)
{
    public async Task SendAsync(InvoiceModel invoice, CancellationToken ct = default)
    {
        var html = await engine.RenderByNameAsync("Invoice Email", invoice, ct);

        await emailClient.SendAsync(new EmailMessage
        {
            To      = invoice.CustomerEmail,
            Subject = $"Invoice #{invoice.Number}",
            HtmlBody = html
        }, ct);
    }
}

Managing Templates

Templates are stored in SQL Server and managed through TemplateBuilder.Editor. Install it in any ASP.NET Core app to get the full create/edit/version UI:

dotnet add package TemplateBuilder.Editor

Both packages share the same database schema — point them at the same connection string. If you already have TemplateBuilder.Editor installed you do not need TemplateBuilder.Core separately; Editor includes the rendering engine.


What's New

v2.0.0

  • Two-state save model — templates managed via TemplateBuilder.Editor now save each version as either Draft or Active. This package's render API is unaffected in shape but is now Active-version-aware — see below.
  • Breaking: render API now serves the last Active version, not simply the newest one. RenderAsync / RenderByNameAsync walk version history for the highest-numbered version with IsActive = true; a newer Draft version is skipped. See the ITemplateEngine section above for the two new exceptions this introduces (TemplateInactiveException, NoActiveVersionException) and the change to when TemplateNotFoundException is thrown.

v1.0.5

  • Fix: This package README was still advertising 1.0.3 as current after 1.0.4 shipped — the version bump wasn't repacked into the actual .nupkg. Now confirmed fixed by extracting and inspecting the published package before every push.

v1.0.4

  • Dependency updates — HtmlSanitizer 9.0.892 → 9.2.995 and Scriban 7.2.0 → 7.2.6, clearing known moderate/high-severity NuGet security advisories. Microsoft.Data.SqlClient, EF Core SqlServer, and Microsoft.Extensions.* packages bumped to their latest 10.0.x patch releases. No breaking changes.

Updating

dotnet add package TemplateBuilder.Core --version <new-version>
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 108 8/22/2026
1.0.4 113 8/16/2026
1.0.3 143 5/31/2026
1.0.2 108 5/31/2026
1.0.1 128 5/30/2026
1.0.0 103 5/22/2026