Skip to content

Commit

Permalink
Add documentation about FlushAsync
Browse files Browse the repository at this point in the history
  • Loading branch information
ltrzesniewski committed Apr 6, 2024
1 parent 05fb617 commit 8ff647d
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 2 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,25 @@ The `RazorTemplate` base class provides `Render` and `RenderAsync` methods to ex

Templates are stateful and not thread-safe, so it is advised to always create new instances of the templates to render.

### Flushing partial output

By default, the output of a template is buffered while it is executing, then copied to the provided writer when finished. This is necessary for features such as layouts to be supported, but may not always be desired.

The `RazorTemplate` class provides a `FlushAsync` method which will copy the buffered output to the provided `TextWriter` and then flush the writer:

<!-- snippet: TemplateWithFlush.Usage -->
<a id='snippet-templatewithflush.usage'></a>
```cshtml
<div>Lightweight content goes here.</div>
@await FlushAsync()
<div>Slower to render content goes here.</div>
```
<sup><a href='/src/RazorBlade.IntegrationTest/Examples/TemplateWithFlush.cshtml#L2-L6' title='Snippet source file'>snippet source</a> | <a href='#snippet-templatewithflush.usage' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

> [!IMPORTANT]
> Flushing is not compatible with layout usage.
### MSBuild

The source generator will process `RazorBlade` MSBuild items which have the `.cshtml` file extension.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@inherits RazorBlade.HtmlTemplate
@* begin-snippet: TemplateWithFlush.Usage *@
<div>Lightweight content goes here.</div>
@await FlushAsync()
<div>Slower to render content goes here.</div>
@* end-snippet *@
7 changes: 7 additions & 0 deletions src/RazorBlade.IntegrationTest/PageWithFlush.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@inherits RazorBlade.HtmlTemplate
<h2>Hello, world!</h2>
This is the body contents before flushing.
@await FlushAsync()
This is the body contents after flushing.
@await FlushAsync()
This is the body contents after a second flushing.
1 change: 1 addition & 0 deletions src/RazorBlade.IntegrationTest/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public static void Main()
WriteTemplate(new TestTemplate { Name = "World" });
WriteTemplate(new TestTemplateWithModel(new FooBarModelClass { Foo = "Foo", Bar = "Bar" }));
WriteTemplate(new PageWithLayout());
WriteTemplate(new PageWithFlush());
}

private static void WriteTemplate(RazorTemplate template)
Expand Down
13 changes: 11 additions & 2 deletions src/RazorBlade.Library/RazorTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,20 @@ private protected virtual async Task<IRazorExecutionResult> ExecuteAsyncCore(Tex
/// <summary>
/// Writes the buffered output to the target output then flushes the output stream.
/// </summary>
/// <returns>
/// An empty <see cref="IEncodedContent"/>, which allows using a direct expression: <c>@await FlushAsync()</c>
/// </returns>
/// <remarks>
/// This feature is not compatible with layouts.
/// </remarks>
protected internal Task FlushAsync()
=> _executionScope?.FlushAsync() ?? Task.CompletedTask;
protected internal async Task<IEncodedContent> FlushAsync()
{
if (_executionScope is not { } executionScope)
throw new InvalidOperationException("The template is not executing.");

await executionScope.FlushAsync().ConfigureAwait(false);
return HtmlString.Empty;
}

/// <summary>
/// Executes the template and appends the result to <see cref="Output"/>.
Expand Down

0 comments on commit 8ff647d

Please sign in to comment.