Skip to content

Commit 6bcf49d

Browse files
Remove temporary APIs now Razor compiler is updated (#51252)
# Remove temporary APIs now Razor compiler is updated The Razor Compiler now supports `@rendermode` and `@formname` natively, so use that. ## Description While waiting for the Razor Compiler's native support for `@rendermode` and `@formname`, we had some temporary APIs. They are less nice to use and don't perform as well. We have always planned to remove them by the time .NET 8 ships. This PR actually removes them and switches all the tests and templates over to the new native syntax. Since this PR is changing the project template anyway, it also implements the "remove unnecessary top-level Components folder in wasm template" (#51167) Fixes #50225 Fixes #51167 ## Customer Impact We have to remove these APIs because otherwise they end up having to be supported forever (or at least, years), and (1) they are now unnecessary and ugly, and (2) they harm perf even if you're not using them, because the way they work requires the renderer to keep checking whether you just used them. ## Regression? - [ ] Yes - [x] No [If yes, specify the version the behavior has regressed from] ## Risk - [ ] High - [x] Medium - [ ] Low It's a meaningful change to the syntax that also involves some template changes. However we always planned to make this change, and couldn't have done it earlier because the compiler changes were not available until now. Also we are still waiting for a build of VS that includes the necessary change, so until then, VS will show red squigglies for the new syntax (though it still compiles and runs successfully). ## Verification - [x] Manual (required) - [x] Automated ## Packaging changes reviewed? - [ ] Yes - [ ] No - [x] N/A
1 parent 0d0aa33 commit 6bcf49d

File tree

50 files changed

+162
-369
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+162
-369
lines changed

src/Components/Components/src/PublicAPI.Unshipped.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ Microsoft.AspNetCore.Components.RenderHandle.DispatchExceptionAsync(System.Excep
2626
*REMOVED*Microsoft.AspNetCore.Components.NavigationManager.ToAbsoluteUri(string! relativeUri) -> System.Uri!
2727
Microsoft.AspNetCore.Components.NavigationManager.ToAbsoluteUri(string? relativeUri) -> System.Uri!
2828
Microsoft.AspNetCore.Components.Rendering.ComponentState.LogicalParentComponentState.get -> Microsoft.AspNetCore.Components.Rendering.ComponentState?
29-
Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder.AddComponentParameter(int sequence, string! name, Microsoft.AspNetCore.Components.IComponentRenderMode! renderMode) -> void
3029
*REMOVED*Microsoft.AspNetCore.Components.RouteData.RouteData(System.Type! pageType, System.Collections.Generic.IReadOnlyDictionary<string!, object!>! routeValues) -> void
3130
*REMOVED*Microsoft.AspNetCore.Components.RouteData.RouteValues.get -> System.Collections.Generic.IReadOnlyDictionary<string!, object!>!
3231
Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder.AddComponentRenderMode(Microsoft.AspNetCore.Components.IComponentRenderMode! renderMode) -> void

src/Components/Components/src/Rendering/RenderTreeBuilder.cs

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ public sealed class RenderTreeBuilder : IDisposable
2727
private RenderTreeFrameType? _lastNonAttributeFrameType;
2828
private bool _hasSeenAddMultipleAttributes;
2929
private Dictionary<string, int>? _seenAttributeNames;
30-
private IComponentRenderMode? _pendingComponentCallSiteRenderMode; // TODO: Remove when Razor compiler supports call-site @rendermode
31-
private string? _pendingNamedSubmitEvent; // TODO: Remove when Razor compiler supports @formname
3230

3331
/// <summary>
3432
/// The reserved parameter name used for supplying child content.
@@ -45,8 +43,6 @@ public sealed class RenderTreeBuilder : IDisposable
4543
/// <param name="elementName">A value representing the type of the element.</param>
4644
public void OpenElement(int sequence, string elementName)
4745
{
48-
CompletePendingNamedSubmitEvent();
49-
5046
// We are entering a new scope, since we track the "duplicate attributes" per
5147
// element/component we might need to clean them up now.
5248
if (_hasSeenAddMultipleAttributes)
@@ -66,8 +62,6 @@ public void OpenElement(int sequence, string elementName)
6662
/// </summary>
6763
public void CloseElement()
6864
{
69-
CompletePendingNamedSubmitEvent();
70-
7165
var indexOfEntryBeingClosed = _openElementIndices.Pop();
7266

7367
// We might be closing an element with only attributes, run the duplicate cleanup pass
@@ -80,16 +74,6 @@ public void CloseElement()
8074
_entries.Buffer[indexOfEntryBeingClosed].ElementSubtreeLengthField = _entries.Count - indexOfEntryBeingClosed;
8175
}
8276

83-
// TODO: Remove this once Razor supports @formname
84-
private void CompletePendingNamedSubmitEvent()
85-
{
86-
if (_pendingNamedSubmitEvent is not null)
87-
{
88-
AddNamedEvent("onsubmit", _pendingNamedSubmitEvent);
89-
_pendingNamedSubmitEvent = default;
90-
}
91-
}
92-
9377
/// <summary>
9478
/// Appends a frame representing markup content.
9579
/// </summary>
@@ -237,16 +221,7 @@ public void AddAttribute(int sequence, string name, string? value)
237221
AssertCanAddAttribute();
238222
if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component)
239223
{
240-
// TODO: Remove this once the Razor compiler is updated to support @formname
241-
// That should compile directly as a call to AddNamedEvent.
242-
if (string.Equals(name, "@formname", StringComparison.Ordinal) && _lastNonAttributeFrameType == RenderTreeFrameType.Element)
243-
{
244-
_pendingNamedSubmitEvent = value!;
245-
}
246-
else
247-
{
248-
_entries.AppendAttribute(sequence, name, value);
249-
}
224+
_entries.AppendAttribute(sequence, name, value);
250225
}
251226
else
252227
{
@@ -530,28 +505,6 @@ public void OpenComponent(int sequence, [DynamicallyAccessedMembers(Component)]
530505
OpenComponentUnchecked(sequence, componentType);
531506
}
532507

533-
/// <summary>
534-
/// Temporary API until Razor compiler is updated. This will be removed before .NET 8 ships.
535-
/// </summary>
536-
public void AddComponentParameter(int sequence, string name, IComponentRenderMode renderMode)
537-
{
538-
if (string.Equals(name, "@rendermode", StringComparison.Ordinal))
539-
{
540-
// When the Razor compiler is updated, <SomeComponent @rendermode="@RenderMode.WebAssembly" /> would compile directly as a call
541-
// to AddComponentRenderMode(RenderMode.WebAssembly), which must appear after all attributes. Until then we'll intercept regular
542-
// parameters with this name and IComponentRenderMode values. Unfortunately we can't guarantee that the parameter will appear after
543-
// all other parameters (e.g., ChildContent would always go later), so use this inefficient trick to defer adding it.
544-
// It won't be needed once the Razor compiler supports @rendermode.
545-
_pendingComponentCallSiteRenderMode = renderMode;
546-
}
547-
else
548-
{
549-
// For other parameter names, the developer is doing something custom so just pass the parameter as normal
550-
// This special case will also not be relevant once we have @rendermode
551-
AddComponentParameter(sequence, name, (object)renderMode);
552-
}
553-
}
554-
555508
/// <summary>
556509
/// Appends a frame representing a component parameter.
557510
/// </summary>
@@ -600,8 +553,6 @@ public void SetKey(object? value)
600553

601554
private void OpenComponentUnchecked(int sequence, [DynamicallyAccessedMembers(Component)] Type componentType)
602555
{
603-
CompletePendingNamedSubmitEvent();
604-
605556
// We are entering a new scope, since we track the "duplicate attributes" per
606557
// element/component we might need to clean them up now.
607558
if (_hasSeenAddMultipleAttributes)
@@ -621,12 +572,6 @@ private void OpenComponentUnchecked(int sequence, [DynamicallyAccessedMembers(Co
621572
/// </summary>
622573
public void CloseComponent()
623574
{
624-
if (_pendingComponentCallSiteRenderMode is not null)
625-
{
626-
AddComponentRenderMode(_pendingComponentCallSiteRenderMode);
627-
_pendingComponentCallSiteRenderMode = null;
628-
}
629-
630575
var indexOfEntryBeingClosed = _openElementIndices.Pop();
631576

632577
// We might be closing a component with only attributes. Run the attribute cleanup pass

src/Components/Components/test/Rendering/RenderTreeBuilderTest.cs

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,39 +2171,6 @@ public void CannotAddParametersAfterComponentRenderMode()
21712171
Assert.Equal($"Component parameters may only be added immediately after frames of type {RenderTreeFrameType.Component}", ex.Message);
21722172
}
21732173

2174-
[Fact]
2175-
public void TemporaryApiForCallSiteComponentRenderModeWorksEvenIfOtherParameterAddedAfter()
2176-
{
2177-
// For the temporary syntax rendermode=@something (as opposed to @rendermode=@something), we can't guarantee
2178-
// the Razor compiler will emit the AddComponentParameter call for rendermode last. For example if there's a
2179-
// ChildContent it will actually emit that last. So for the temporary syntax to be usable it has to support
2180-
// other component parameters being added afterwards, even though that does not need to be supported for
2181-
// AddComponentRenderMode (since the compiler can be sure to add that after all component parameters).
2182-
2183-
// Arrange
2184-
var builder = new RenderTreeBuilder();
2185-
var renderMode = new TestRenderMode();
2186-
2187-
// Act
2188-
builder.OpenComponent<TestComponent>(0);
2189-
builder.AddComponentParameter(1, "param", 123);
2190-
builder.AddComponentParameter(2, "@rendermode", renderMode);
2191-
builder.AddComponentParameter(3, "anotherparam", 456);
2192-
builder.CloseComponent();
2193-
2194-
// Assert
2195-
Assert.Collection(
2196-
builder.GetFrames().AsEnumerable(),
2197-
frame =>
2198-
{
2199-
AssertFrame.Component<TestComponent>(frame, 4, 0);
2200-
Assert.True(frame.ComponentFrameFlags.HasFlag(ComponentFrameFlags.HasCallerSpecifiedRenderMode));
2201-
},
2202-
frame => AssertFrame.Attribute(frame, "param", 123, 1),
2203-
frame => AssertFrame.Attribute(frame, "anotherparam", 456, 3),
2204-
frame => AssertFrame.ComponentRenderMode(frame, renderMode));
2205-
}
2206-
22072174
[Fact]
22082175
public void CanAddNamedEvent()
22092176
{
@@ -2301,34 +2268,6 @@ public void CannotAddAttributesAfterNamedEvent()
23012268
Assert.Equal($"Attributes may only be added immediately after frames of type {RenderTreeFrameType.Element} or {RenderTreeFrameType.Component}", ex.Message);
23022269
}
23032270

2304-
[Fact]
2305-
public void TemporaryApiForFormNameEventsWorksEvenIfAttributesAddedAfter()
2306-
{
2307-
// TODO: Remove this once the Razor compiler is updated to support @formname directly
2308-
2309-
// Arrange
2310-
var builder = new RenderTreeBuilder();
2311-
var renderMode = new TestRenderMode();
2312-
2313-
// Act
2314-
builder.OpenElement(0, "div");
2315-
builder.AddAttribute(1, "attr1", 123);
2316-
builder.AddAttribute(2, "@formname", "some custom name");
2317-
builder.AddAttribute(3, "attr2", 456);
2318-
builder.OpenElement(4, "other");
2319-
builder.CloseElement();
2320-
builder.CloseElement();
2321-
2322-
// Assert
2323-
Assert.Collection(
2324-
builder.GetFrames().AsEnumerable(),
2325-
frame => AssertFrame.Element(frame, "div", 5, 0),
2326-
frame => AssertFrame.Attribute(frame, "attr1", "123", 1),
2327-
frame => AssertFrame.Attribute(frame, "attr2", "456", 3),
2328-
frame => AssertFrame.NamedEvent(frame, "onsubmit", "some custom name"),
2329-
frame => AssertFrame.Element(frame, "other", 1));
2330-
}
2331-
23322271
private class TestComponent : IComponent
23332272
{
23342273
public void Attach(RenderHandle renderHandle) { }

src/Components/Endpoints/test/HotReloadServiceTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ private static RazorComponentEndpointDataSource<TComponent> CreateDataSource<TCo
195195

196196
private class StaticComponent : ComponentBase { }
197197

198-
[RenderModeInteractiveServer]
198+
[TestRenderMode<InteractiveServerRenderMode>]
199199
private class ServerComponent : ComponentBase { }
200200

201201
private class MockEndpointProvider : RenderModeEndpointProvider

src/Components/Endpoints/test/RazorComponentEndpointDataSourceTest.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.AspNetCore.Builder;
66
using Microsoft.AspNetCore.Components.Discovery;
77
using Microsoft.AspNetCore.Components.Endpoints.Infrastructure;
8+
using Microsoft.AspNetCore.Components.Endpoints.Tests;
89
using Microsoft.AspNetCore.Components.Web;
910
using Microsoft.AspNetCore.Routing;
1011
using Microsoft.AspNetCore.Routing.Patterns;
@@ -242,13 +243,13 @@ private RazorComponentEndpointDataSource<TComponent> CreateDataSource<TComponent
242243
return result;
243244
}
244245

245-
[RenderModeInteractiveServer]
246+
[TestRenderMode<InteractiveServerRenderMode>]
246247
private class ServerComponent : ComponentBase { }
247248

248-
[RenderModeInteractiveAuto]
249+
[TestRenderMode<InteractiveAutoRenderMode>]
249250
private class AutoComponent : ComponentBase { }
250251

251-
[RenderModeInteractiveWebAssembly]
252+
[TestRenderMode<InteractiveWebAssemblyRenderMode>]
252253
private class WebAssemblyComponent : ComponentBase { }
253254

254255
private class ServerEndpointProvider : RenderModeEndpointProvider

src/Components/Endpoints/test/TestComponents/InteractiveGreetingServer.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@using Microsoft.AspNetCore.Components.Web
2-
@attribute [RenderModeInteractiveServer]
2+
@rendermode RenderMode.InteractiveServer
33

44
<p>Hello @(Name ?? "(null)")!</p>
55

src/Components/Endpoints/test/TestComponents/InteractiveGreetingServerNonPrerendered.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@using Microsoft.AspNetCore.Components.Web
2-
@attribute [RenderModeInteractiveServer(false)]
2+
@rendermode @(new InteractiveServerRenderMode(prerender: false))
33

44
<p>Hello @(Name ?? "(null)")!</p>
55

src/Components/Endpoints/test/TestComponents/InteractiveGreetingWebAssembly.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@using Microsoft.AspNetCore.Components.Web
2-
@attribute [RenderModeInteractiveWebAssembly]
2+
@rendermode RenderMode.InteractiveWebAssembly
33

44
<p>Hello @(Name ?? "(null)")!</p>
55

src/Components/Endpoints/test/TestComponents/InteractiveGreetingWebAssemblyNonPrerendered.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@using Microsoft.AspNetCore.Components.Web
2-
@attribute [RenderModeInteractiveWebAssembly(false)]
2+
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
33

44
<p>Hello @(Name ?? "(null)")!</p>
55

src/Components/Endpoints/test/TestComponents/InteractiveWithInteractiveChild.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@using Microsoft.AspNetCore.Components.Web
2-
@attribute [RenderModeInteractiveWebAssembly]
2+
@rendermode RenderMode.InteractiveWebAssembly
33

44
<h1>This is @nameof(InteractiveWithInteractiveChild)</h1>
55

0 commit comments

Comments
 (0)