Skip to content

Commit 4076bad

Browse files
authored
Allow DefaultPageLoader.LoadAsync to work with CompiledPageActionDescriptor (#35325)
With a fallback page, DefaultPageLoader might observe a mix of PageActionDescriptor and CompiledPageActionDescriptor instances. Currently encountering the latter results in an exception. Fixes #35060
1 parent fad9658 commit 4076bad

File tree

5 files changed

+50
-3
lines changed

5 files changed

+50
-3
lines changed

src/Mvc/Mvc.RazorPages/src/Infrastructure/DefaultPageLoader.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ public override Task<CompiledPageActionDescriptor> LoadAsync(PageActionDescripto
4545
throw new ArgumentNullException(nameof(actionDescriptor));
4646
}
4747

48+
if (actionDescriptor is CompiledPageActionDescriptor compiledPageActionDescriptor)
49+
{
50+
// It's possible for some code paths of PageLoaderMatcherPolicy to invoke LoadAsync with an instance
51+
// of CompiledPageActionDescriptor. In that case, we'll return the instance as-is.
52+
compiledPageActionDescriptor.CompiledPageActionDescriptorTask ??= Task.FromResult(compiledPageActionDescriptor);
53+
return compiledPageActionDescriptor.CompiledPageActionDescriptorTask;
54+
}
55+
4856
var task = actionDescriptor.CompiledPageActionDescriptorTask;
4957

5058
if (task != null)

src/Mvc/Mvc.RazorPages/test/Infrastructure/DefaultPageLoaderTest.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ public async Task LoadAsync_IsUniquePerPageDescriptor()
294294
},
295295
};
296296

297-
298297
var transformer = new Mock<RoutePatternTransformer>();
299298
transformer
300299
.Setup(t => t.SubstituteRequiredValues(It.IsAny<RoutePattern>(), It.IsAny<object>()))
@@ -335,6 +334,29 @@ public async Task LoadAsync_IsUniquePerPageDescriptor()
335334
Assert.NotSame(result1, result2);
336335
}
337336

337+
[Fact]
338+
public async Task LoadAsync_CompiledPageActionDescriptor_ReturnsSelf()
339+
{
340+
// Arrange
341+
var mvcOptions = Options.Create(new MvcOptions());
342+
var endpointFactory = new ActionEndpointFactory(Mock.Of<RoutePatternTransformer>(), Enumerable.Empty<IRequestDelegateFactory>());
343+
var loader = new DefaultPageLoader(
344+
new[] { Mock.Of<IPageApplicationModelProvider>() },
345+
Mock.Of<IViewCompilerProvider>(),
346+
endpointFactory,
347+
RazorPagesOptions,
348+
mvcOptions);
349+
var pageDescriptor = new CompiledPageActionDescriptor();
350+
351+
// Act
352+
var result1 = await loader.LoadAsync(pageDescriptor, new EndpointMetadataCollection());
353+
var result2 = await loader.LoadAsync(pageDescriptor, new EndpointMetadataCollection());
354+
355+
// Assert
356+
Assert.Same(pageDescriptor, result1);
357+
Assert.Same(pageDescriptor, result2);
358+
}
359+
338360
private static IViewCompilerProvider GetCompilerProvider()
339361
{
340362
var compiledItem = TestRazorCompiledItem.CreateForView(typeof(object), "/Views/Index.cshtml");

src/Mvc/test/Mvc.FunctionalTests/RazorBuildTest.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
@@ -50,6 +50,19 @@ public async Task Rzc_LocalPageWithDifferentContent_IsUsed()
5050
Assert.Equal("Hello from runtime-compiled rzc page!", responseBody.Trim());
5151
}
5252

53+
[Fact]
54+
public async Task RuntimeCompilation_WithFallbackPage_Works()
55+
{
56+
// Regression test for https://github.com/dotnet/aspnetcore/issues/35060
57+
// Act
58+
var response = await Client.GetAsync("Fallback");
59+
60+
// Assert
61+
await response.AssertStatusCodeAsync(HttpStatusCode.OK);
62+
var responseBody = await response.Content.ReadAsStringAsync();
63+
Assert.Equal("Hello from fallback page!", responseBody.Trim());
64+
}
65+
5366
[Fact]
5467
public async Task Rzc_LocalViewWithDifferentContent_IsUsed()
5568
{
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@page
2+
3+
Hello from fallback page!

src/Mvc/test/WebSites/RazorBuildWebSite/Startup.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.IO;
@@ -27,6 +27,7 @@ public void Configure(IApplicationBuilder app)
2727
{
2828
endpoints.MapDefaultControllerRoute();
2929
endpoints.MapRazorPages();
30+
endpoints.MapFallbackToPage("/Fallback");
3031
});
3132
}
3233

0 commit comments

Comments
 (0)