|
3 | 3 |
|
4 | 4 | using System.Diagnostics;
|
5 | 5 | using System.Runtime.ExceptionServices;
|
| 6 | +using System.Text.Encodings.Web; |
6 | 7 | using Microsoft.AspNetCore.Components.RenderTree;
|
| 8 | +using Microsoft.AspNetCore.Html; |
7 | 9 | using Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers;
|
8 | 10 | using Microsoft.Extensions.Logging;
|
9 | 11 |
|
@@ -47,14 +49,11 @@ protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
|
47 | 49 |
|
48 | 50 | public async Task<ComponentRenderedText> RenderComponentAsync(Type componentType, ParameterView initialParameters)
|
49 | 51 | {
|
50 |
| - var (componentId, frames) = await CreateInitialRenderAsync(componentType, initialParameters); |
51 |
| - |
52 |
| - var viewBuffer = new ViewBuffer(_viewBufferScope, nameof(HtmlRenderer), ViewBuffer.ViewPageSize); |
| 52 | + var component = InstantiateComponent(componentType); |
| 53 | + var componentId = AssignRootComponentId(component); |
53 | 54 |
|
54 |
| - var context = new HtmlRenderingContext { HtmlContentBuilder = viewBuffer, }; |
55 |
| - var newPosition = RenderFrames(context, frames, 0, frames.Count); |
56 |
| - Debug.Assert(newPosition == frames.Count); |
57 |
| - return new ComponentRenderedText(componentId, context.HtmlContentBuilder); |
| 55 | + await RenderRootComponentAsync(componentId, initialParameters); |
| 56 | + return new ComponentRenderedText(componentId, new ComponentHtmlContent(this, componentId)); |
58 | 57 | }
|
59 | 58 |
|
60 | 59 | public Task<ComponentRenderedText> RenderComponentAsync<TComponent>(ParameterView initialParameters) where TComponent : IComponent
|
@@ -248,21 +247,50 @@ private static int RenderAttributes(
|
248 | 247 | return position + maxElements;
|
249 | 248 | }
|
250 | 249 |
|
251 |
| - private async Task<(int, ArrayRange<RenderTreeFrame>)> CreateInitialRenderAsync(Type componentType, ParameterView initialParameters) |
| 250 | + private ViewBuffer GetRenderedHtmlContent(int componentId) |
252 | 251 | {
|
253 |
| - var component = InstantiateComponent(componentType); |
254 |
| - var componentId = AssignRootComponentId(component); |
| 252 | + var viewBuffer = new ViewBuffer(_viewBufferScope, nameof(HtmlRenderer), ViewBuffer.ViewPageSize); |
| 253 | + var context = new HtmlRenderingContext(viewBuffer); |
255 | 254 |
|
256 |
| - await RenderRootComponentAsync(componentId, initialParameters); |
| 255 | + var frames = GetCurrentRenderTreeFrames(componentId); |
| 256 | + var newPosition = RenderFrames(context, frames, 0, frames.Count); |
| 257 | + Debug.Assert(newPosition == frames.Count); |
257 | 258 |
|
258 |
| - return (componentId, GetCurrentRenderTreeFrames(componentId)); |
| 259 | + return viewBuffer; |
259 | 260 | }
|
260 | 261 |
|
261 | 262 | private sealed class HtmlRenderingContext
|
262 | 263 | {
|
263 |
| - public ViewBuffer HtmlContentBuilder { get; init; } |
| 264 | + public HtmlRenderingContext(ViewBuffer viewBuffer) |
| 265 | + { |
| 266 | + HtmlContentBuilder = viewBuffer; |
| 267 | + } |
| 268 | + |
| 269 | + public ViewBuffer HtmlContentBuilder { get; } |
264 | 270 |
|
265 | 271 | public string ClosestSelectValueAsString { get; set; }
|
266 | 272 | }
|
| 273 | + |
| 274 | + /// <summary> |
| 275 | + /// A <see cref="IHtmlContent"/> that defers rendering component markup until <see cref="IHtmlContent.WriteTo(TextWriter, HtmlEncoder)"/> |
| 276 | + /// is called. |
| 277 | + /// </summary> |
| 278 | + private sealed class ComponentHtmlContent : IHtmlContent |
| 279 | + { |
| 280 | + private readonly HtmlRenderer _renderer; |
| 281 | + private readonly int _componentId; |
| 282 | + |
| 283 | + public ComponentHtmlContent(HtmlRenderer renderer, int componentId) |
| 284 | + { |
| 285 | + _renderer = renderer; |
| 286 | + _componentId = componentId; |
| 287 | + } |
| 288 | + |
| 289 | + public void WriteTo(TextWriter writer, HtmlEncoder encoder) |
| 290 | + { |
| 291 | + var actualHtmlContent = _renderer.GetRenderedHtmlContent(_componentId); |
| 292 | + actualHtmlContent.WriteTo(writer, encoder); |
| 293 | + } |
| 294 | + } |
267 | 295 | }
|
268 | 296 |
|
0 commit comments