Skip to content

Commit 96da75d

Browse files
authored
Merge pull request #50963 from dotnet-maestro-bot/merge/release/8.0-rc2-to-release/8.0
[automated] Merge branch 'release/8.0-rc2' => 'release/8.0'
2 parents 8b27376 + 9a71712 commit 96da75d

File tree

122 files changed

+5905
-787
lines changed

Some content is hidden

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

122 files changed

+5905
-787
lines changed

src/Antiforgery/src/AntiforgeryApplicationBuilderExtensions.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
using Microsoft.AspNetCore.Antiforgery;
55
using Microsoft.AspNetCore.Antiforgery.Internal;
6-
using Microsoft.AspNetCore.Routing;
7-
using Microsoft.Extensions.DependencyInjection;
86

97
namespace Microsoft.AspNetCore.Builder;
108

@@ -26,19 +24,6 @@ public static IApplicationBuilder UseAntiforgery(this IApplicationBuilder builde
2624
builder.VerifyAntiforgeryServicesAreRegistered();
2725

2826
builder.Properties[AntiforgeryMiddlewareSetKey] = true;
29-
30-
// The anti-forgery middleware adds annotations to HttpContext.Items to indicate that it has run
31-
// that will be validated by the EndpointsRoutingMiddleware later. To do this, we need to ensure
32-
// that routing has run and set the endpoint feature on the HttpContext associated with the request.
33-
if (builder.Properties.TryGetValue(RerouteHelper.GlobalRouteBuilderKey, out var routeBuilder) && routeBuilder is not null)
34-
{
35-
return builder.Use(next =>
36-
{
37-
var newNext = RerouteHelper.Reroute(builder, routeBuilder, next);
38-
var antiforgery = builder.ApplicationServices.GetRequiredService<IAntiforgery>();
39-
return new AntiforgeryMiddleware(antiforgery, newNext).Invoke;
40-
});
41-
}
4227
builder.UseMiddleware<AntiforgeryMiddleware>();
4328

4429
return builder;

src/Antiforgery/src/Microsoft.AspNetCore.Antiforgery.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,5 @@
2626

2727
<ItemGroup>
2828
<Compile Include="$(SharedSourceRoot)HttpExtensions.cs" LinkBase="Shared"/>
29-
<Compile Include="$(SharedSourceRoot)Reroute.cs" LinkBase="Shared"/>
3029
</ItemGroup>
3130
</Project>

src/Components/Web.JS/dist/Release/blazor.web.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Components/Web.JS/src/Services/WebRootComponentManager.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type RootComponentInfo = {
3737
assignedRendererId?: WebRendererId;
3838
uniqueIdAtLastUpdate?: number;
3939
interactiveComponentId?: number;
40-
}
40+
};
4141

4242
export class WebRootComponentManager implements DescriptorHandler, RootComponentManager<never> {
4343
private readonly _rootComponents = new Set<RootComponentInfo>();
@@ -193,7 +193,7 @@ export class WebRootComponentManager implements DescriptorHandler, RootComponent
193193
}
194194

195195
private circuitMayHaveNoRootComponents() {
196-
const isCircuitInUse = this.hasAnyExistingOrPendingServerComponents();
196+
const isCircuitInUse = this.rendererHasExistingOrPendingComponents(WebRendererId.Server, 'server', 'auto');
197197
if (isCircuitInUse) {
198198
// Clear the timeout because we know the circuit is in use.
199199
clearTimeout(this._circuitInactivityTimeoutId);
@@ -208,31 +208,38 @@ export class WebRootComponentManager implements DescriptorHandler, RootComponent
208208

209209
// Start a new timeout to dispose the circuit unless it starts getting used.
210210
this._circuitInactivityTimeoutId = setTimeout(() => {
211-
if (!this.hasAnyExistingOrPendingServerComponents()) {
211+
if (!this.rendererHasExistingOrPendingComponents(WebRendererId.Server, 'server', 'auto')) {
212212
disposeCircuit();
213213
this._circuitInactivityTimeoutId = undefined;
214214
}
215215
}, this._circuitInactivityTimeoutMs) as unknown as number;
216216
}
217217

218-
private hasAnyExistingOrPendingServerComponents(): boolean {
219-
// If there are active Blazor Server components on the page, we shouldn't dispose the circuit.
220-
const renderer = getRendererer(WebRendererId.Server);
221-
if (renderer && renderer.getRootComponentCount() > 0) {
218+
private rendererHasComponents(rendererId: WebRendererId): boolean {
219+
const renderer = getRendererer(rendererId);
220+
return renderer !== undefined && renderer.getRootComponentCount() > 0;
221+
}
222+
223+
private rendererHasExistingOrPendingComponents(rendererId: WebRendererId, ...descriptorTypesToConsider: ComponentMarker['type'][]): boolean {
224+
if (this.rendererHasComponents(rendererId)) {
222225
return true;
223226
}
224227

225-
// If we have SSR components that may become Blazor Server components in the future,
226-
// we shouldn't dispose the circuit.
228+
// We consider SSR'd components on the page that may get activated using the specified renderer.
227229
for (const { descriptor: { type }, assignedRendererId } of this._rootComponents) {
228-
if (assignedRendererId === WebRendererId.Server) {
229-
// The component has been assigned to use Blazor Server.
230+
if (assignedRendererId === rendererId) {
231+
// The component has been assigned to use the specified renderer.
230232
return true;
231233
}
232234

233-
if (assignedRendererId === undefined && (type === 'auto' || type === 'server')) {
234-
// The component has not been assigned a renderer yet, so it's possible it might
235-
// use Blazor Server.
235+
if (assignedRendererId !== undefined) {
236+
// The component has been assigned to use another renderer.
237+
continue;
238+
}
239+
240+
if (descriptorTypesToConsider.indexOf(type) !== -1) {
241+
// The component has not been assigned a renderer yet, but it might get activated with the specified renderer
242+
// if it doesn't get removed from the page.
236243
return true;
237244
}
238245
}
@@ -298,9 +305,20 @@ export class WebRootComponentManager implements DescriptorHandler, RootComponent
298305
}
299306

300307
private getAutoRenderMode(): 'webassembly' | 'server' | null {
301-
// If the WebAssembly runtime has loaded, we will always use WebAssembly
302-
// for auto components. Otherwise, we'll wait to activate root components
303-
// until we determine whether the WebAssembly runtime can be loaded quickly.
308+
// If WebAssembly components exist or may exist soon, use WebAssembly.
309+
if (this.rendererHasExistingOrPendingComponents(WebRendererId.WebAssembly, 'webassembly')) {
310+
return 'webassembly';
311+
}
312+
313+
// If Server components exist or may exist soon, use WebAssembly.
314+
if (this.rendererHasExistingOrPendingComponents(WebRendererId.Server, 'server')) {
315+
return 'server';
316+
}
317+
318+
// If no interactive components are on the page, we use WebAssembly
319+
// if the WebAssembly runtime has loaded. Otherwise, we'll wait to activate
320+
// root components until we determine whether the WebAssembly runtime can be
321+
// loaded quickly.
304322
if (hasLoadedWebAssemblyPlatform()) {
305323
return 'webassembly';
306324
}

src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,84 @@ public void AutoRenderMode_CanUseBlazorWebAssembly_WhenMultipleAutoComponentsAre
720720
Browser.Equal("WebAssembly", () => Browser.FindElement(By.Id("render-mode-2")).Text);
721721
}
722722

723+
[Fact]
724+
public void AutoRenderMode_UsesBlazorWebAssembly_WhenBothServerAndWebAssemblyComponentsExist()
725+
{
726+
Navigate($"{ServerPathBase}/streaming-interactivity");
727+
Browser.Equal("Not streaming", () => Browser.FindElement(By.Id("status")).Text);
728+
729+
Browser.Click(By.Id(AddWebAssemblyPrerenderedId));
730+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-0")).Text);
731+
Browser.Equal("WebAssembly", () => Browser.FindElement(By.Id("render-mode-0")).Text);
732+
733+
Browser.Click(By.Id(AddServerPrerenderedId));
734+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-1")).Text);
735+
Browser.Equal("Server", () => Browser.FindElement(By.Id("render-mode-1")).Text);
736+
737+
Browser.Click(By.Id(AddAutoPrerenderedId));
738+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-2")).Text);
739+
Browser.Equal("WebAssembly", () => Browser.FindElement(By.Id("render-mode-2")).Text);
740+
}
741+
742+
[Fact]
743+
public void AutoRenderMode_UsesBlazorServer_WhenOnlyServerComponentsExist_EvenAfterWebAssemblyResourcesLoad()
744+
{
745+
Navigate(ServerPathBase);
746+
Browser.Equal("Hello", () => Browser.Exists(By.TagName("h1")).Text);
747+
ForceWebAssemblyResourceCacheMiss();
748+
749+
Navigate($"{ServerPathBase}/streaming-interactivity");
750+
Browser.Equal("Not streaming", () => Browser.FindElement(By.Id("status")).Text);
751+
752+
// We start by adding a WebAssembly component to ensure the WebAssembly runtime
753+
// will be cached after we refresh the page.
754+
Browser.Click(By.Id(AddWebAssemblyPrerenderedId));
755+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-0")).Text);
756+
Browser.Equal("WebAssembly", () => Browser.FindElement(By.Id("render-mode-0")).Text);
757+
758+
Browser.Click(By.Id($"remove-counter-link-0"));
759+
Browser.DoesNotExist(By.Id("is-interactive-0"));
760+
761+
Browser.Navigate().Refresh();
762+
763+
Browser.Click(By.Id(AddServerPrerenderedId));
764+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-1")).Text);
765+
Browser.Equal("Server", () => Browser.FindElement(By.Id("render-mode-1")).Text);
766+
767+
// Verify that Auto mode will use Blazor Server, even though the WebAssembly runtime is cached
768+
Browser.Click(By.Id(AddAutoPrerenderedId));
769+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-2")).Text);
770+
Browser.Equal("Server", () => Browser.FindElement(By.Id("render-mode-2")).Text);
771+
}
772+
773+
[Fact]
774+
public void AutoRenderMode_UsesBlazorServer_AfterWebAssemblyComponentsNoLongerExist_ButServerComponentsDo()
775+
{
776+
Navigate($"{ServerPathBase}/streaming-interactivity");
777+
Browser.Equal("Not streaming", () => Browser.FindElement(By.Id("status")).Text);
778+
779+
Browser.Click(By.Id(AddWebAssemblyPrerenderedId));
780+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-0")).Text);
781+
Browser.Equal("WebAssembly", () => Browser.FindElement(By.Id("render-mode-0")).Text);
782+
783+
Browser.Click(By.Id(AddServerPrerenderedId));
784+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-1")).Text);
785+
Browser.Equal("Server", () => Browser.FindElement(By.Id("render-mode-1")).Text);
786+
787+
Browser.Click(By.Id(AddAutoPrerenderedId));
788+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-2")).Text);
789+
Browser.Equal("WebAssembly", () => Browser.FindElement(By.Id("render-mode-2")).Text);
790+
791+
// Remove all WebAssembly components
792+
Browser.Click(By.Id("remove-counter-link-0"));
793+
Browser.Click(By.Id("remove-counter-link-2"));
794+
795+
// Verify that Blazor Server gets used
796+
Browser.Click(By.Id(AddAutoPrerenderedId));
797+
Browser.Equal("True", () => Browser.FindElement(By.Id("is-interactive-3")).Text);
798+
Browser.Equal("Server", () => Browser.FindElement(By.Id("render-mode-3")).Text);
799+
}
800+
723801
[Fact]
724802
public void Circuit_ShutsDown_WhenAllBlazorServerComponentsGetRemoved()
725803
{

src/DefaultBuilder/src/WebApplicationBuilder.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Diagnostics;
55
using System.Diagnostics.CodeAnalysis;
66
using System.Reflection;
7-
using Microsoft.AspNetCore.Antiforgery;
87
using Microsoft.AspNetCore.Authentication;
98
using Microsoft.AspNetCore.Authorization;
109
using Microsoft.AspNetCore.Hosting;
@@ -25,7 +24,6 @@ public sealed class WebApplicationBuilder : IHostApplicationBuilder
2524
private const string EndpointRouteBuilderKey = "__EndpointRouteBuilder";
2625
private const string AuthenticationMiddlewareSetKey = "__AuthenticationMiddlewareSet";
2726
private const string AuthorizationMiddlewareSetKey = "__AuthorizationMiddlewareSet";
28-
private const string AntiforgeryMiddlewareSetKey = "__AntiforgeryMiddlewareSet";
2927
private const string UseRoutingKey = "__UseRouting";
3028

3129
private readonly HostApplicationBuilder _hostApplicationBuilder;
@@ -453,15 +451,6 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui
453451
}
454452
}
455453

456-
if (serviceProviderIsService?.IsService(typeof(IAntiforgery)) is true)
457-
{
458-
if (!_builtApplication.Properties.ContainsKey(AntiforgeryMiddlewareSetKey))
459-
{
460-
_builtApplication.Properties[AntiforgeryMiddlewareSetKey] = true;
461-
app.UseAntiforgery();
462-
}
463-
}
464-
465454
// Wire the source pipeline to run in the destination pipeline
466455
var wireSourcePipeline = new WireSourcePipeline(_builtApplication);
467456
app.Use(wireSourcePipeline.CreateMiddleware);

0 commit comments

Comments
 (0)