Introduction

ServiceStack Templates is a simple and elegant, highly-extensible, sandboxed,
high-performance general-purpose templating engine for .NET 4.5 and .NET Core.
It's designed from the ground-up to be incrementally adoptable where its basic usage is simple enough
for non-technical users to use whilst it progressively enables access to more power and functionality allowing it to scale up to
support full server-rendering Web Server workloads and beyond. Its high-fidelity with JavaScript syntax allows it to use a common
language for seamlessly integrating with client-side JavaScript Single Page App frameworks where its syntax is designed to be
compatible with Vue filters.

Instant Startup

There's no pre-compilation, pre-loading or Startup penalty, all Pages are lazily loaded on first use and cached for fast subsequent
evaluation. Its instant Startup, fast runtime performance and sandboxed isolation opens it up to a myriad of new use-cases which
can enhance .NET Apps with a rich Live programming experience.

Fast Runtime Performance

ServiceStack Templates is fast, parsing is done using StringSegment for minimal GC pressure, all I/O is non-blocking inc. async
writes to OutputStream's. There's no buffering: Layouts, Pages and Partials are asynchronously written to a forward only stream.
There's no runtime reflection, each filter or binding within template expressions executes compiled and cached C# Expressions.

They're also pure at the code-level where it doesn't have any coupling to concrete dependencies, components or static classes. Default filters
don't mutate any external state. There's no imperative statements, everything is an expression forcing a more readable and declarative
programming-style that's easier to quickly determine the subject of expressions and the states that need to be met for filters to be executed.
Conceptually Templates are "evaluated" in that they take in arguments, filters and templates as inputs and evaluates them to an output stream.
They're highly testable by design where the same environment used to create the context can easily be re-created in Unit tests,
including simulating pages in a File System using its In Memory Virtual File System.

Optimal Development Experience

The above attributes enables an instant iterative development workflow with a Live Development experience that supports
configuration-free Hot Reloading out of the box that lets you build entire
Wep Apps and Web APIs without ever having to compile or manually Refresh pages.

Simplicity end-to-end

There are 2 main concepts in Template Expressions: Arguments - variables which can be made available
through a number of cascading sources and Filters - public C# methods that exist in the list of
TemplateFilters registered in the PageResult or TemplateContext that templates are executed within.

Layouts, Pages and Partials are all just "pages", evaluated in the same way with access to arguments and filters. Parameters passed
to partials are just scoped arguments, accessed like any other arguments. Typically pages are sourced from the configured
File System but when access to more advanced functionality is required they can also be Code Pages implemented
in pure C# that are otherwise interchangeable and can be used anywhere a normal page is requested.

There's no language constructs or reserved words in Templates itself, all functionality is implemented inside filters.
There's also nothing special about the Default Filters included with Templates
other than they're pre-registered by default. External filters can do anything built-in filters can do which can just
as easily be shadowed or removed giving you a clean slate where you're free to define your own
language and preferred language naming scheme.

They're non-invasive, by default ServiceStack's View Engine is configured to handle
.html files but can be configured to handle any html extension or text file format.
When a page doesn't contain any Template Expressions it's contents are returned as-is, making it easy to adopt in existing
static websites.

Templates are sandboxed, they can't call static or instance methods, invoke setters or access anything
outside of the arguments and filters made available to them. Without filters, expressions wouldn't have any methods
they can call, leaving them with the only thing they can do which is access arguments and replace their variable placeholders,
including the {{ page }} placeholder to tell the Layout where to render the page:

Quick Example Walkthrough

_layout.html

page.html

To render the pages we first create and initialize a TemplateContext

varcontext = newTemplateContext().Init();

The TemplateContext is the sandbox where all templates are executed within, everything your templates have access to and generates
is maintained within the TemplateContext. Once initialize you can start using it to evaluate templates which you can do with just:

varoutput = context.EvaluateTemplate("{{ 12.34 | currency }}");

Templates only have access to filters and arguments defined within its Context, which for an empty Context are the comprehensive
suite of safe Default Filters and HTML Filters.

Typically you'll want to use ServiceStack templates to render entire pages which are sourced from its configured
Virtual File System which uses an In Memory Virtual
File System by default that we can programmatically populate:

Templates are rendered using a PageResult essentially a rendering context that needs to be provided the Page to render:

varpageResult = newPageResult(context.GetPage("page"));

The template output can then be asynchronously rendered to any Stream:

awaitpageResult.WriteToAsync(responseStream);

Or to access the output as a string you can use the convenience extension method:

stringoutput = awaitpageResult.RenderToStringAsync();

All I/O within Templates is non-blocking, but if you're evaluating an adhoc template or using the default In Memory Virtual FileSystem
there's no I/O so you can safely block to get the generated output with:

stringoutput = pageResult.Result;

Both APIs returns the result you see in the Live Example above.

Cascading Resolution

There's no forced special centralized folders like /Views or /Views/Shared required to store layouts or share partials or
artificial "Areas" concept to isolate website sections. Different websites or sections are intuitively grouped into different
folders and Templates automatically resolves the closest layout it finds for each page. Cascading resolution also applies to
including files or partial pages where you can use just its name to resolve the closest one, or an absolute path from the
WebRootPath to include a specific partial or file from a different folder.

High-level, Declarative and Intent-based

High-level APIs are usually synonymous with being slow by virtue of paying a penalty for their high-level abstraction,
but in the domain of I/O and Streams such-as rendering text to Streams they make it trivial to compose high-level functionality
that's implemented more efficiently than would be typically written in C# / ASP.NET MVC Apps.

The intent of Template code should be clear even if it's the first time reading it. From left-to-right we can deduce that it
retrieves a url from the quote table, downloads its contents of and converts it to markdown before replacing the text "Razor" and
"2010" and displaying the raw non-HTML encoded html output.

Implementation using ASP.NET MVC

In MVC the typical and easiest approach would be to create a an MVC Controller Action, use EF to make a sync call to access the database,
a sync call with a new HTTP Client to download the content which is buffered inside the Controller action before returned inside a View Model
that is handed off to MVC to execute the View inside the default Layout.

Implementation using Templates

What does Templates do? lets step through the first filter:

What filter implementation gets called depends on which DB Filter is registered, if your RDBMS supports ADO.NET's
async API you can register
TemplateDbFiltersAsync
to execute all queries asynchronously, otherwise if using an RDBMS whose ADO.NET Provider doesn't support async you can register the
TemplateDbFilters
to execute each DB request synchronously without paying for any pseudo-async overhead, in each case the exact same code executes
the most optimal ADO.NET APIs. Template also benefits from using the much faster
OrmLite and also saves on the abstraction cost from generating a
parameterized SQL Statement from a Typed Expression-based API.

Arguments chain

The next question becomes what is id bound to? Similar to JavaScript's prototype chain it resolves the closest argument
in its Arguments hierarchy, e.g. when evaluated as a view page it could be set by the
queryString or when the same page is evaluated as a partial it could be set from the scoped arguments it was called with.

Async I/O

The url returned from the db is then passed to the urlContents filter which if it was the last filter in the expression
avoids any buffering by asynchronously streaming the url content stream directly to the forward-only HTTP Response Stream:

{{ url | urlContents }}

urlContents is a Block Filter which instead of returning a value writes its
response to the OutputStream it's given. But then how could we convert it to Markdown if it's already written to the Response Stream?
Templates analyzes the Expression's AST to determine if there's any filters remaining, if there is it gives the urlContents
Block filter a MemoryStream to write to, then forwards its buffered output to the next filter. Since they don't return values,
the only thing that can come after a Block Filter are other Block filters or Stream Transformers.
markdown is one such Filter Transformer which takes in a stream of Markdown
and returns a Stream of HTML.

{{ url | urlContents | markdown }}

Same intent, different implementations

The assignTo filter is used to set a value in the current scope. After Block Filters, a different assignTo Block Filter
is used with the same name and purpose but a different implementation that reads all the contents of the stream into a UTF-8 string
and sets a value in the current scope before returning an empty Stream so nothing is written to the Response.

{{ url | urlContents | markdown | assignTo: quote }}

Once the streamed output is captured and assigned it goes back into becoming a normal argument that opens it up to be
able to use all filters again, which is how we're able to use the string replace filters before rendering the final result :)

Using the most efficient implementation allowable

So whilst it conceptually looks like each filter is transforming large buffered strings inside every filter, the expression is
inspected to utilize the most efficient implementation allowable. At the same time filters are not statically bound to
any implementation so you could for instance insert a Custom Filter before the Default
Filters containing the same name and arguments count to have templates execute your custom filters instead, all whilst the template's
source code and intent remains untouched.

Intent-based code is easier to augment

If it was later discovered that some URLs were slow or rate-limited and you needed to introduce caching, your original C# code
would require a fair amount of rework, in templates you can simply add WithCache to call the
urlContentsWithCache filter to return locally cached contents
on subsequent requests.

{{ url | urlContentsWithCache | markdown }}

Simplified Language

As there's very little ceremony in Templates, a chain of filters looks like it's using its own DSL to accomplish each task and
given implementing and registering custom filters is trivial you're
encouraged to write the intent of your code first then implement any filters that are missing to realize its intent. Once
you've captured the intent of what you want to do, it's less likely to ever need to change, focus is instead on
fixing any bugs and making the filter implementations as efficient as possible, which benefits all existing code using the same filter.

To improve readability and make it more approachable, templates aims to normalize the mechanics of the underlying implementation from
the code's intent so you can use the same syntax to access an argument, e.g. {{ arg }} as you would a filter without
arguments {{ now }} and just like JavaScript you can use obj.Property syntax to access both a public property
on a Type or an entry in a Dictionary.

Late-bound flexibility

There's no static coupling to concrete classes, static methods or other filters, ambiguous method exceptions or namespace collisions.
Each filter is self-contained and can easily be shared and dropped into any Web App by
registering them in a list. Inspired by the power and
flexibility in Smalltalk and LISP, filters are late-bound at run-time to the first matching filter
in the user-defined list of TemplateFilters. This ability to shadow filters enables high-level intent-based APIs decoupled from implementations which
sendToAutoQuery leverages to automatically route filter invocations to
the appropriate implementation depending of if it's an AutoQuery RDBMS or an
AutoQuery Data request, masking their implementations as a transparent detail.
This flexibility also makes it easy create proxies, intercept and inject behavior like logging or profiling without modifying existing
filter implementations or template source code.