Mundane is a lightweight "no magic" web framework for .NET.
This package provides Mundane with a view engine using a Mustache-like syntax.
See the Mundane documentation for more information.
Install the Mundane.ViewEngines.Mustache nuget package, then in the Mundane startup code add a dependency to MustacheViews
, passing in an IFileProvider
pointing to the view templates.
For example in ASP.NET:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var dependencies = new Dependencies(
new Dependency<Configuration>(new Configuration(env)),
new Dependency<DataRepository>(request => new DataRepositorySqlServer(
request.Dependency<Configuration>().ConnectionString)),
new Dependency<MustacheViews>(new MustacheViews(
new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Views")))));
var routing = new Routing(
routeConfiguration =>
{
routeConfiguration.Get("/", HomeController.HomePage);
routeConfiguration.Get("/data/{id}", DataController.GetData);
routeConfiguration.Post("/data/{id}", DataController.UpdateData);
});
app.UseMundane(dependencies, routing);
}
Then in your controller call MustacheView()
on the ResponseStream
, passing the name of the template file and optionally a view model.
internal static class DataController
{
internal static async ValueTask<Response> GetData(Request request)
{
var dataRepository = request.Dependency<DataRepository>();
var data = await dataRepository.GetData(request.Route("id"));
return Response.Ok(responseStream => responseStream.MustacheView("DataPage.html", data));
}
}
These methods all belong to:
public static class MustacheViewEngine
The following are the standard signatures where the MustacheViews
object will be retrieved from the Request
dependencies, and the output will be written to the response stream. An exception will be thrown if the MustacheViews
object has not been registered as a dependency.
public static async ValueTask MustacheView(
this ResponseStream responseStream,
string templatePath);
public static async ValueTask MustacheView(
this ResponseStream responseStream,
string templatePath,
object viewModel);
The following also write the output to the response stream, but expect the MustacheViews
object to be supplied explicitly.
public static async ValueTask MustacheView(
this ResponseStream responseStream,
MustacheViews mustacheViews,
string templatePath);
public static async ValueTask MustacheView(
this ResponseStream responseStream,
MustacheViews mustacheViews,
string templatePath,
object viewModel);
The following expect the MustacheViews
object to be supplied explicitly, and write the output to the supplied Stream
.
public static async ValueTask MustacheView(
Stream outputStream,
MustacheViews mustacheViews,
string templatePath);
public static async ValueTask MustacheView(
Stream outputStream,
MustacheViews mustacheViews,
string templatePath,
object viewModel);
The following expect the MustacheViews
object to be supplied explicitly, and return the output as a string
.
public static async ValueTask<string> MustacheView(
MustacheViews mustacheViews,
string templatePath);
public static async ValueTask<string> MustacheView(
MustacheViews mustacheViews,
string templatePath,
object viewModel);
See the Mustache specification for more detail. The following is a brief outline of what is supported.
To output a value from a view model use {{name}}
where "name" is a property or dictionary key on the view model.
Variables are HTML escaped e.g. if name
contained <script>
it would be output as <script>
.
To output a value without HTML escaping use {{&name}}
. Note that triple braces {{{name}}}
for achieving the same thing is not supported.
{{#name}}
begins a section and {{/name}}
ends a section.
Falsy values or empty lists for name
will not output the section contents.
Truthy values will output the section contents once. Non-empty lists will output the section contents once for each item in the list.
An inverted section begins with {{^name}}
and ends with{{/name}}
.
Falsy values or empty lists for name
will output the section contents once.
Truthy values or non-empty lists will not output the section contents.
Comments are specified with {{! This is a comment. }}
. Everything between the braces will be ignored.
Partials are specified with {{> mypartial.html }}
. The contents of mypartial.html
will be output in place of the tag, and will inherit the current view model context.
URLs can be transformed in the template by using {{~ /some-url }}
, for example by adding the base path of the application (e.g. /my-app/some-url
).
The URL resolver is optionally passed to the MustacheViews
constructor, and has the signature string UrlResolver(string pathBase, string url)
, e.g.
new MustacheViews(fileProvider, (pathBase, url) => pathBase + TransformUrl(url))
If no URL resolver is specified, the default is (pathBase, url) => pathBase + url
.
Layouts (as described here) are also supported.
{{! layout.html }}
<html>
<head>
<title>{{$Title}}Default Title{{/Title}}</title>
</head>
<body>
{{$Body}}Default Body{{/Body}}
</body>
</html>
{{! mypage.html }}
{{< layout.html }}
{{$Title}}My Title{{/Title}}
{{$Body}}My Body{{/Body}}
{{/ layout.html }}
The output of mypage.html
would be:
<html>
<head>
<title>My Title</title>
</head>
<body>
My Body
</body>
</html>
The layout replacements are optional, in which case the contents of the replacement blocks in the layout will be output.
{{! alternatepage.html }}
{{< layout.html }}
{{/ layout.html }}
The output of alternatepage.html
would be:
<html>
<head>
<title>Default Title</title>
</head>
<body>
Default Body
</body>
</html>