From b8d927b8efb3647b8c4aab0e27db23a32a81f189 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 2 Mar 2022 21:19:26 -0800 Subject: [PATCH 1/2] Modify HtmlRenderer to update content when a component re-renders --- .../src/Buffers/ViewBuffer.cs | 2 +- .../src/RazorComponents/HtmlRenderer.cs | 54 ++++++++++++++----- .../BlazorServerTemplateTest.cs | 2 +- .../BlazorServerWeb-CSharp/Pages/_Host.cshtml | 33 ++++++++++-- .../Pages/_Layout.cshtml | 32 ----------- .../test/template-baselines.json | 6 --- 6 files changed, 72 insertions(+), 57 deletions(-) delete mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Layout.cshtml diff --git a/src/Mvc/Mvc.ViewFeatures/src/Buffers/ViewBuffer.cs b/src/Mvc/Mvc.ViewFeatures/src/Buffers/ViewBuffer.cs index e1c738220cc6..089dd0323104 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/Buffers/ViewBuffer.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/Buffers/ViewBuffer.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers; /// An that is backed by a buffer provided by . /// [DebuggerDisplay("{DebuggerToString()}")] -internal class ViewBuffer : IHtmlContentBuilder +internal sealed class ViewBuffer : IHtmlContentBuilder { public const int PartialViewPageSize = 32; public const int TagHelperPageSize = 32; diff --git a/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/HtmlRenderer.cs b/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/HtmlRenderer.cs index 2fa943a3497a..b2213734514c 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/HtmlRenderer.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/HtmlRenderer.cs @@ -3,7 +3,9 @@ using System.Diagnostics; using System.Runtime.ExceptionServices; +using System.Text.Encodings.Web; using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers; using Microsoft.Extensions.Logging; @@ -47,14 +49,11 @@ protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) public async Task RenderComponentAsync(Type componentType, ParameterView initialParameters) { - var (componentId, frames) = await CreateInitialRenderAsync(componentType, initialParameters); - - var viewBuffer = new ViewBuffer(_viewBufferScope, nameof(HtmlRenderer), ViewBuffer.ViewPageSize); + var component = InstantiateComponent(componentType); + var componentId = AssignRootComponentId(component); - var context = new HtmlRenderingContext { HtmlContentBuilder = viewBuffer, }; - var newPosition = RenderFrames(context, frames, 0, frames.Count); - Debug.Assert(newPosition == frames.Count); - return new ComponentRenderedText(componentId, context.HtmlContentBuilder); + await RenderRootComponentAsync(componentId, initialParameters); + return new ComponentRenderedText(componentId, new ComponentHtmlContent(this, componentId)); } public Task RenderComponentAsync(ParameterView initialParameters) where TComponent : IComponent @@ -248,21 +247,50 @@ private static int RenderAttributes( return position + maxElements; } - private async Task<(int, ArrayRange)> CreateInitialRenderAsync(Type componentType, ParameterView initialParameters) + private ViewBuffer GetRenderedHtmlContent(int componentId) { - var component = InstantiateComponent(componentType); - var componentId = AssignRootComponentId(component); + var viewBuffer = new ViewBuffer(_viewBufferScope, nameof(HtmlRenderer), ViewBuffer.ViewPageSize); + var context = new HtmlRenderingContext(viewBuffer); - await RenderRootComponentAsync(componentId, initialParameters); + var frames = GetCurrentRenderTreeFrames(componentId); + var newPosition = RenderFrames(context, frames, 0, frames.Count); + Debug.Assert(newPosition == frames.Count); - return (componentId, GetCurrentRenderTreeFrames(componentId)); + return viewBuffer; } private sealed class HtmlRenderingContext { - public ViewBuffer HtmlContentBuilder { get; init; } + public HtmlRenderingContext(ViewBuffer viewBuffer) + { + HtmlContentBuilder = viewBuffer; + } + + public ViewBuffer HtmlContentBuilder { get; } public string ClosestSelectValueAsString { get; set; } } + + /// + /// A that defers rendering component markup until + /// is called. + /// + private sealed class ComponentHtmlContent : IHtmlContent + { + private readonly HtmlRenderer _renderer; + private readonly int _componentId; + + public ComponentHtmlContent(HtmlRenderer renderer, int componentId) + { + _renderer = renderer; + _componentId = componentId; + } + + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + var actualHtmlContent = _renderer.GetRenderedHtmlContent(_componentId); + actualHtmlContent.WriteTo(writer, encoder); + } + } } diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs index 1a04fd77aa2b..6fa17ed08919 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs @@ -25,7 +25,7 @@ public BlazorServerTemplateTest(ProjectFactoryFixture projectFactory) public override string ProjectType { get; } = "blazorserver"; - [Theory(Skip = "https://github.com/dotnet/aspnetcore/issues/30761")] + [Theory] [InlineData(BrowserKind.Chromium)] public async Task BlazorServerTemplateWorks_NoAuth(BrowserKind browserKind) { diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Host.cshtml b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Host.cshtml index c8b0009bc2a2..132aad8a77a4 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Host.cshtml +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Host.cshtml @@ -1,8 +1,33 @@ @page "/" +@using Microsoft.AspNetCore.Components.Web @namespace BlazorServerWeb_CSharp.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -@{ - Layout = "_Layout"; -} - + + + + + + + + + + + + + + +
+ + An error has occurred. This application may no longer respond until reloaded. + + + An unhandled exception has occurred. See browser dev tools for details. + + Reload + 🗙 +
+ + + + diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Layout.cshtml b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Layout.cshtml deleted file mode 100644 index c265ac4b9e1d..000000000000 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Pages/_Layout.cshtml +++ /dev/null @@ -1,32 +0,0 @@ -@using Microsoft.AspNetCore.Components.Web -@namespace BlazorServerWeb_CSharp.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers - - - - - - - - - - - - - - @RenderBody() - -
- - An error has occurred. This application may no longer respond until reloaded. - - - An unhandled exception has occurred. See browser dev tools for details. - - Reload - 🗙 -
- - - - diff --git a/src/ProjectTemplates/test/template-baselines.json b/src/ProjectTemplates/test/template-baselines.json index b707dcd78819..9dabc86be55a 100644 --- a/src/ProjectTemplates/test/template-baselines.json +++ b/src/ProjectTemplates/test/template-baselines.json @@ -1262,7 +1262,6 @@ "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", - "Pages/_Layout.cshtml", "Properties/launchSettings.json", "Shared/LoginDisplay.razor", "Shared/MainLayout.razor", @@ -1302,7 +1301,6 @@ "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", - "Pages/_Layout.cshtml", "Properties/launchSettings.json", "Shared/LoginDisplay.razor", "Shared/MainLayout.razor", @@ -1342,7 +1340,6 @@ "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", - "Pages/_Layout.cshtml", "Properties/launchSettings.json", "Shared/LoginDisplay.razor", "Shared/MainLayout.razor", @@ -1382,7 +1379,6 @@ "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", - "Pages/_Layout.cshtml", "Properties/launchSettings.json", "Shared/MainLayout.razor", "Shared/MainLayout.razor.css", @@ -1421,7 +1417,6 @@ "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", - "Pages/_Layout.cshtml", "Properties/launchSettings.json", "Shared/LoginDisplay.razor", "Shared/MainLayout.razor", @@ -1461,7 +1456,6 @@ "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", - "Pages/_Layout.cshtml", "Properties/launchSettings.json", "Shared/LoginDisplay.razor", "Shared/MainLayout.razor", From 64a884caf3c4b8598db66a6b5551a15360751266 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 3 Mar 2022 10:15:57 -0800 Subject: [PATCH 2/2] Undo unskipped test --- .../BlazorTemplates.Tests/BlazorServerTemplateTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs index 6fa17ed08919..1a04fd77aa2b 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs @@ -25,7 +25,7 @@ public BlazorServerTemplateTest(ProjectFactoryFixture projectFactory) public override string ProjectType { get; } = "blazorserver"; - [Theory] + [Theory(Skip = "https://github.com/dotnet/aspnetcore/issues/30761")] [InlineData(BrowserKind.Chromium)] public async Task BlazorServerTemplateWorks_NoAuth(BrowserKind browserKind) {