| File: HtmlRendering\StaticHtmlRenderer.cs | Web Access |
| Project: src\aspnetcore\src\Components\Web\src\Microsoft.AspNetCore.Components.Web.csproj (Microsoft.AspNetCore.Components.Web) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using System.Runtime.ExceptionServices; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web.HtmlRendering; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Components.HtmlRendering.Infrastructure; /// <summary> /// A <see cref="Renderer"/> subclass that is intended for static HTML rendering. Application /// developers should not normally use this class directly. Instead, use /// <see cref="HtmlRenderer"/> for a more convenient API. /// </summary> public partial class StaticHtmlRenderer : Renderer { private static readonly RendererInfo _componentPlatform = new RendererInfo("Static", isInteractive: false); private readonly NavigationManager? _navigationManager; /// <summary> /// Constructs an instance of <see cref="StaticHtmlRenderer"/>. /// </summary> /// <param name="serviceProvider">The <see cref="IServiceProvider"/> to be used when initializing components.</param> /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param> public StaticHtmlRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) : base(serviceProvider, loggerFactory) { _navigationManager = serviceProvider.GetService<NavigationManager>(); _htmlEncoder = serviceProvider.GetService<HtmlEncoder>() ?? HtmlEncoder.Default; _javaScriptEncoder = serviceProvider.GetService<JavaScriptEncoder>() ?? JavaScriptEncoder.Default; } /// <inheritdoc/> public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault(); /// <inheritdoc/> protected internal override RendererInfo RendererInfo => _componentPlatform; /// <summary> /// Adds a root component of the specified type and begins rendering it. /// </summary> /// <param name="componentType">The component type. This must implement <see cref="IComponent"/>.</param> /// <param name="initialParameters">Parameters for the component.</param> /// <returns>An <see cref="HtmlRootComponent"/> that can be used to obtain the rendered HTML.</returns> public HtmlRootComponent BeginRenderingComponent( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType, ParameterView initialParameters) { var component = InstantiateComponent(componentType); return BeginRenderingComponent(component, initialParameters); } /// <summary> /// Adds a root component and begins rendering it. /// </summary> /// <param name="component">The root component instance to be added and rendered. This must not already be associated with any renderer.</param> /// <param name="initialParameters">Parameters for the component.</param> /// <returns>An <see cref="HtmlRootComponent"/> that can be used to obtain the rendered HTML.</returns> public HtmlRootComponent BeginRenderingComponent( IComponent component, ParameterView initialParameters) { var componentId = AssignRootComponentId(component); var quiescenceTask = RenderRootComponentAsync(componentId, initialParameters); if (quiescenceTask.IsFaulted) { ExceptionDispatchInfo.Capture(quiescenceTask.Exception.InnerException ?? quiescenceTask.Exception).Throw(); } return new HtmlRootComponent(this, componentId, quiescenceTask); } /// <inheritdoc/> protected override void HandleException(Exception exception) => ExceptionDispatchInfo.Capture(exception).Throw(); /// <inheritdoc/> protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) { // By default we return a canceled task. This has the effect of making it so that the // OnAfterRenderAsync callbacks on components don't run by default. // This way, by default prerendering gets the correct behavior and other renderers // override the UpdateDisplayAsync method already, so those components can // either complete a task when the client acknowledges the render, or return a canceled task // when the renderer gets disposed. // We believe that returning a canceled task is the right behavior as we expect that any class // that subclasses this class to provide an implementation for a given rendering scenario respects // the contract that OnAfterRender should only be called when the display has successfully been updated // and the application is interactive. (Element and component references are populated and JavaScript interop // is available). return CanceledRenderTask; } internal new ArrayRange<RenderTreeFrame> GetCurrentRenderTreeFrames(int componentId) => base.GetCurrentRenderTreeFrames(componentId); }