Hello Daniel!
", prerenderedContent); var epilogue = match.Groups["epilogue"].Value; - var epilogueMarker = JsonSerializer.DeserializeHello (null)!
", prerenderedContent); var epilogue = match.Groups["epilogue"].Value; - var epilogueMarker = JsonSerializer.DeserializeHello SomeName!
", prerenderedContent); var epilogue = match.Groups["epilogue"].Value; - var epilogueMarker = JsonSerializer.DeserializeHello (null)!
", prerenderedContent); var epilogue = match.Groups["epilogue"].Value; - var epilogueMarker = JsonSerializer.DeserializeIncrement amount: @IncrementAmount
Interactive: @_isInteractive
+Render mode: @_renderMode
Current count: @_currentCount
@@ -11,6 +12,7 @@ @code { private int _currentCount = 0; private bool _isInteractive = false; + private string _renderMode = "SSR"; [Parameter, EditorRequired] public int IncrementAmount { get; set; } @@ -31,6 +33,7 @@ if (firstRender) { _isInteractive = true; + _renderMode = OperatingSystem.IsBrowser() ? "WebAssembly" : "Server"; StateHasChanged(); } } diff --git a/src/Shared/Components/ComponentMarker.cs b/src/Shared/Components/ComponentMarker.cs new file mode 100644 index 000000000000..4799556361d3 --- /dev/null +++ b/src/Shared/Components/ComponentMarker.cs @@ -0,0 +1,96 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +namespace Microsoft.AspNetCore.Components; + +internal struct ComponentMarker +{ + public const string ServerMarkerType = "server"; + public const string WebAssemblyMarkerType = "webassembly"; + public const string AutoMarkerType = "auto"; + + #region Common marker data + + // The marker type. Can be "server", "webassembly", or "auto". + public string? Type { get; set; } + + // A string to allow the clients to differentiate between prerendered + // and non prerendered components and to uniquely identify start and end + // markers in prererendered components. + // The value will be null if this marker represents a non-prerendered component. + public string? PrerenderId { get; set; } + + // An additional string that the browser can use when comparing markers to determine + // whether they represent different component instances. + public string? Key { get; set; } + + #endregion + + #region Server marker data + + // The order in which this component was rendered/produced + // on the server. It matches the number on the descriptor + // and is used to prevent an infinite amount of components + // from being rendered from the client-side. + public int? Sequence { get; set; } + + // A data-protected payload that allows the server to validate the legitimacy + // of the invocation. + // The value will be null for end markers. + public string? Descriptor { get; set; } + + #endregion + + #region WebAssembly marker data + + // The assembly containing the component type. + public string? Assembly { get; set; } + + // The full name of the component type. + public string? TypeName { get; set; } + + // Serialized definitions of the component's parameters. + public string? ParameterDefinitions { get; set; } + + // Serialized values of the component's parameters. + public string? ParameterValues { get; set; } + + #endregion + + public static ComponentMarker Create(string type, bool prerendered, string? key) + { + return new() + { + Type = type, + PrerenderId = prerendered ? GeneratePrerenderId() : null, + Key = key, + }; + } + + public void WriteServerData(int sequence, string descriptor) + { + Sequence = sequence; + Descriptor = descriptor; + } + + public void WriteWebAssemblyData(string assembly, string typeName, string parameterDefinitions, string parameterValues) + { + Assembly = assembly; + TypeName = typeName; + ParameterDefinitions = parameterDefinitions; + ParameterValues = parameterValues; + } + + public ComponentEndMarker? ToEndMarker() + => PrerenderId is null ? default : new() { PrerenderId = PrerenderId }; + + private static string GeneratePrerenderId() + => Guid.NewGuid().ToString("N"); +} + +internal struct ComponentEndMarker +{ + public string? PrerenderId { get; set; } +} diff --git a/src/Shared/Components/ServerComponentMarker.cs b/src/Shared/Components/ServerComponentMarker.cs deleted file mode 100644 index 9c684a02e717..000000000000 --- a/src/Shared/Components/ServerComponentMarker.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Globalization; -using Microsoft.AspNetCore.Components.RenderTree; - -namespace Microsoft.AspNetCore.Components; - -#nullable enable // This is shared-source with Mvc.ViewFeatures which doesn't enable nullability by default - -// Represents the serialized invocation to a component. -// We serialize this marker into a comment in the generated -// HTML. -internal struct ServerComponentMarker -{ - public const string ServerMarkerType = "server"; - - private ServerComponentMarker(string? type, string? descriptor, int? sequence, string? key, string? prerenderId) : this() - { - Type = type; - PrerenderId = prerenderId; - Descriptor = descriptor; - Sequence = sequence; - Key = key; - } - - // The order in which this component was rendered/produced - // on the server. It matches the number on the descriptor - // and is used to prevent an infinite amount of components - // from being rendered from the client-side. - public int? Sequence { get; set; } - - // The marker type. Right now "server" is the only valid value. - // The value will be null for end markers. - public string? Type { get; set; } - - // A string to allow the clients to differentiate between prerendered - // and non prerendered components and to uniquely identify start and end - // markers in prererendered components. - // The value will be null if this marker represents a non-prerendered component. - public string? PrerenderId { get; set; } - - // A data-protected payload that allows the server to validate the legitimacy - // of the invocation. - // The value will be null for end markers. - public string? Descriptor { get; set; } - - // An additional string that the browser can use when comparing markers to determine - // whether they represent different component instances. - public string? Key { get; set; } - - // Creates a marker for a prerendered component. - public static ServerComponentMarker Prerendered(int sequence, string descriptor, string? key) => - new ServerComponentMarker(ServerMarkerType, descriptor, sequence, key, Guid.NewGuid().ToString("N")); - - // Creates a marker for a non prerendered component - public static ServerComponentMarker NonPrerendered(int sequence, string descriptor, string? key) => - new ServerComponentMarker(ServerMarkerType, descriptor, sequence, key, null); - - // Creates the end marker for a prerendered component. - public ServerComponentMarker GetEndRecord() - { - if (PrerenderId == null) - { - throw new InvalidOperationException("Can't get an end record for non-prerendered components."); - } - - return new ServerComponentMarker(null, null, null, null, PrerenderId); - } -} diff --git a/src/Shared/Components/WebAssemblyComponentMarker.cs b/src/Shared/Components/WebAssemblyComponentMarker.cs deleted file mode 100644 index 4e583be9262d..000000000000 --- a/src/Shared/Components/WebAssemblyComponentMarker.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.AspNetCore.Components; - -#nullable enable // This is shared-source with Mvc.ViewFeatures which does not enable nullability by default - -internal struct WebAssemblyComponentMarker -{ - public const string ClientMarkerType = "webassembly"; - - public WebAssemblyComponentMarker(string type, string assembly, string typeName, string parameterDefinitions, string parameterValues, string? key, string? prerenderId) => - (Type, Assembly, TypeName, ParameterDefinitions, ParameterValues, Key, PrerenderId) = (type, assembly, typeName, parameterDefinitions, parameterValues, key, prerenderId); - - public string Type { get; set; } - - public string Assembly { get; set; } - - public string TypeName { get; set; } - - public string ParameterDefinitions { get; set; } - - public string ParameterValues { get; set; } - - public string? Key { get; set; } - - public string? PrerenderId { get; set; } - - internal static WebAssemblyComponentMarker NonPrerendered(string assembly, string typeName, string parameterDefinitions, string parameterValues, string? key) => - new WebAssemblyComponentMarker(ClientMarkerType, assembly, typeName, parameterDefinitions, parameterValues, key, null); - - internal static WebAssemblyComponentMarker Prerendered(string assembly, string typeName, string parameterDefinitions, string parameterValues, string? key) => - new WebAssemblyComponentMarker(ClientMarkerType, assembly, typeName, parameterDefinitions, parameterValues, key, Guid.NewGuid().ToString("N")); - - public WebAssemblyEndComponentMarker GetEndRecord() - { - if (PrerenderId == null) - { - throw new InvalidOperationException("Can't get an end record for non-prerendered components."); - } - - return new WebAssemblyEndComponentMarker { PrerenderId = PrerenderId }; - } -} - -internal struct WebAssemblyEndComponentMarker -{ - public string PrerenderId { get; set; } -}