Add WriteLiteral(ReadOnlyMemory<byte>) for UTF-8 HTML literal support#66429
Draft
DamianEdwards wants to merge 4 commits intomainfrom
Draft
Add WriteLiteral(ReadOnlyMemory<byte>) for UTF-8 HTML literal support#66429DamianEdwards wants to merge 4 commits intomainfrom
DamianEdwards wants to merge 4 commits intomainfrom
Conversation
a0341a2 to
78fce77
Compare
DamianEdwards
commented
Apr 23, 2026
| else | ||
| { | ||
| // For non-UTF-8 encodings or non-buffered writers, decode to string | ||
| // and use the existing string-based write path. |
Member
Author
There was a problem hiding this comment.
Might be better to defer this to the writer chain so that adjacent UTF8 literals could be coalesced and encoded in as a single block?
DamianEdwards
commented
Apr 23, 2026
78fce77 to
050ac81
Compare
Implements UTF-8 HTML literal support for MVC Razor views (issue #65605) with a direct byte write path through the entire writer chain so that UTF-8 literal bytes from Razor-compiled views flow directly to the response stream without ever being converted to a string. Changes: - Add Utf8HtmlLiteralContent: internal IHtmlContent wrapper that carries ReadOnlyMemory<byte> UTF-8 literal bytes through the ViewBuffer pipeline - Add RazorPageBase.WriteLiteral(ReadOnlyMemory<byte>): new public API overload that buffers UTF-8 content when encoding is UTF-8, or decodes to string for non-UTF-8 encodings - Add HttpResponseStreamWriter.WriteUtf8/WriteUtf8Async: public methods that flush pending char data then write raw UTF-8 bytes directly to the underlying stream, bypassing char-to-byte encoding entirely - Add PagedBufferedTextWriter.WriteUtf8/WriteUtf8Async: internal methods that flush buffered chars then forward UTF-8 bytes to the inner writer - Special-case Utf8HtmlLiteralContent in ViewBuffer.WriteTo/WriteToAsync to route through the direct UTF-8 write path when the writer chain supports it, avoiding both string conversion and per-item flush penalty - Add comprehensive unit tests and end-to-end tests verifying bytes flow directly to the response stream - Add example manually-authored generated view classes that simulate what the Razor compiler will emit when it supports u8 string literals Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
gfoidl
reviewed
Apr 23, 2026
| /// The writer's encoding is not UTF-8. | ||
| /// </exception> | ||
| [SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "Required to maintain compatibility")] | ||
| public Task WriteUtf8Async(ReadOnlyMemory<byte> utf8Value, CancellationToken cancellationToken = default) |
Member
There was a problem hiding this comment.
Wonder if we should use ValueTask
- Update WriteLiteral method to accept ReadOnlyMemory<byte> directly. - Remove Utf8HtmlLiteralContent class and integrate its functionality into ViewBuffer. - Modify ViewBufferValue to support UTF-8 encoded values. - Update tests to reflect changes in UTF-8 handling and remove obsolete tests. - Enhance benchmarks for UTF-8 writing performance. Co-authored-by: Copilot <copilot@github.com>
This was referenced Apr 24, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements UTF-8 HTML literal support for MVC Razor views per #65605, with a direct byte write path through the entire writer chain so that UTF-8 literal bytes from Razor-compiled views flow directly to the response stream without ever being converted to a string.
The direct UTF-8 write path
At flush time, when
ViewBufferencounters aUtf8HtmlLiteralContententry:ViewBuffer.WriteToAsyncdetects the writer is aPagedBufferedTextWriterPagedBufferedTextWriter.WriteUtf8Asyncflushes any buffered chars, then forwards to the inner writerHttpResponseStreamWriter.WriteUtf8Asyncflushes any pending char buffer (with encoder finalization), then writes the raw UTF-8 bytes directly to the responseStreamResult: zero string allocations, zero char-to-byte encoding — the compile-time UTF-8 bytes are copied directly to the output.
Changes
Utf8HtmlLiteralContent— InternalIHtmlContentwrapper carryingReadOnlyMemory<byte>through theViewBufferRazorPageBase.WriteLiteral(ReadOnlyMemory<byte>)— New public API. When UTF-8 +ViewBufferTextWriter, buffers asUtf8HtmlLiteralContent. Otherwise decodes to string.HttpResponseStreamWriter.WriteUtf8/WriteUtf8Async— New public methods that flush pending chars then write raw UTF-8 bytes directly to the underlying stream. ThrowsInvalidOperationExceptionif encoding is not UTF-8.PagedBufferedTextWriter.WriteUtf8/WriteUtf8Async— Internal methods that flush buffered chars then forward UTF-8 bytes to the innerHttpResponseStreamWriter(falls back to string for other writers).ViewBuffer.WriteTo/WriteToAsync— RoutesUtf8HtmlLiteralContentthrough the direct UTF-8 path when the writer chain supports it. Avoids both string conversion and per-itemFlushAsyncpenalty.u8literalsTesting
HttpResponseStreamWriter.WriteUtf8tests: direct writes, ordering, non-UTF-8 rejection, disposed state (11 tests)PagedBufferedTextWriter.WriteUtf8tests: forwarding, ordering, fallback (5 tests)ViewBufferend-to-end tests: bytes flow directly to stream through full writer chain (3 tests)Utf8HtmlLiteralContentunit tests (6 tests)RazorPageBase.WriteLiteral(ReadOnlyMemory<byte>)unit tests (5 tests)Fixes #65605