Skip to content

Commit fcc84fd

Browse files
committed
Merge in 'release/6.0' changes
2 parents 4d2a03f + 7c5b80c commit fcc84fd

File tree

18 files changed

+306
-71
lines changed

18 files changed

+306
-71
lines changed

eng/Build.props

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,25 @@
1616
<!-- Exclude the websockets samples for now because they use classic .csproj, which is not yet supported in our build. -->
1717
<ProjectToExclude Include="$(RepoRoot)src\Middleware\WebSockets\samples\**\*.csproj" />
1818

19-
<!-- These projects are meant to be executed by tests. -->
20-
<ProjectToExclude Include="
21-
$(RepoRoot)src\Tools\dotnet-watch\test\TestProjects\**\*.csproj;
22-
$(RepoRoot)src\Tools\Tests.Common\TestProjects\**\*.csproj;
23-
$(RepoRoot)src\Razor\Razor.Design\test\testassets\**\*.*proj;
24-
$(RepoRoot)src\Razor\test\testassets\**\*.*proj;
25-
$(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
26-
$(RepoRoot)src\Components\WebAssembly\Sdk\testassets\**\*.csproj;
27-
" />
19+
<!-- These projects are meant to be referenced only by tests. -->
20+
<ProjectToExclude Include="$(RepoRoot)src\**\testassets\**\*.*proj"
21+
Exclude="$(RepoRoot)src\Components\WebAssembly\testassets\WasmLinkerTest\*.*proj;
22+
$(RepoRoot)src\Components\WebView\Samples\PhotinoPlatform\testassets\PhotinoTestApp\*.*proj;
23+
$(RepoRoot)src\Http\Routing\test\testassets\RoutingSandbox\*.*proj;
24+
$(RepoRoot)src\Security\Authentication\Negotiate\test\testassets\Negotiate.Client\*.*proj;
25+
$(RepoRoot)src\Security\Authentication\Negotiate\test\testassets\Negotiate.Server\*.*proj;
26+
" />
2827

2928
<!-- These projects are not meant to be built in this repo. In the Installers case, must explicitly opt in. -->
3029
<!-- On the other hand, the main spa-templates project is just another project in this repo. -->
3130
<ProjectToExclude Include="
3231
$(RepoRoot)src\submodules\googletest\**\*.*proj;
3332
$(RepoRoot)src\submodules\MessagePack-CSharp\**\*.*proj;
33+
$(RepoRoot)src\submodules\spa-templates\src\content\**\*.csproj;
34+
$(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
3435
$(RepoRoot)src\Installers\**\*.*proj;
35-
$(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
3636
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.*proj;
37-
$(RepoRoot)src\submodules\spa-templates\src\content\**\*.csproj;
37+
$(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
3838
" />
3939

4040
<!-- Exclude the benchmarks because they use <PackageReference>. -->

src/Hosting/test/FunctionalTests/Microsoft.AspNetCore.Hosting.FunctionalTests.csproj

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<Project Sdk="Microsoft.NET.Sdk">
2-
32
<PropertyGroup>
43
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
54

@@ -17,10 +16,20 @@
1716

1817
<ItemGroup>
1918
<ProjectReference Include="$(RepoRoot)src\Hosting\Server.IntegrationTesting\src\Microsoft.AspNetCore.Server.IntegrationTesting.csproj" />
20-
<ProjectReference Include="$(RepoRoot)src\Hosting\test\testassets\IStartupInjectionAssemblyName\IStartupInjectionAssemblyName.csproj" ReferenceOutputAssemblies="false" />
19+
<ProjectReference Include="$(RepoRoot)src\Hosting\test\testassets\BasicLinkedApp\BasicLinkedApp.csproj"
20+
Private="false"
21+
ReferenceOutputAssembly="false"
22+
SkipGetTargetFrameworkProperties="true" />
23+
<ProjectReference Include="$(RepoRoot)src\Hosting\test\testassets\IStartupInjectionAssemblyName\IStartupInjectionAssemblyName.csproj"
24+
Private="false"
25+
ReferenceOutputAssembly="false"
26+
SkipGetTargetFrameworkProperties="true" />
27+
<ProjectReference Include="$(RepoRoot)src\Hosting\test\testassets\Microsoft.AspNetCore.Hosting.TestSites\Microsoft.AspNetCore.Hosting.TestSites.csproj"
28+
Private="false"
29+
ReferenceOutputAssembly="false"
30+
SkipGetTargetFrameworkProperties="true" />
2131

2232
<Reference Include="Microsoft.AspNetCore.Hosting" />
2333
<Reference Include="Microsoft.Extensions.Logging.Console" />
2434
</ItemGroup>
25-
2635
</Project>

src/Mvc/Mvc.Razor.RuntimeCompilation/src/DependencyInjection/RazorRuntimeCompilationMvcCoreBuilderExtensions.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,16 @@ internal static void AddServices(IServiceCollection services)
8787

8888
if (actionDescriptorProvider != null)
8989
{
90+
// RuntimeCompilation registers an instance of PageActionDescriptorProvider(PageADP). CompiledPageADP and runtime compilation
91+
// cannot co-exist since CompiledPageADP will attempt to resolve action descriptors for lazily compiled views (such as for
92+
// ones from non-physical file providers). We'll instead remove CompiledPageActionDescriptors from the DI container if present.
9093
services.Remove(actionDescriptorProvider);
94+
}
9195

92-
// Add PageActionDescriptorProvider and the matcher policy that supports runtime compilation.
93-
// We only want to add support for this if we know AddRazorPages was called. In the absence of this, several services registered by Razor Pages
94-
// will be absent. We'll use the presence of the CompiledPageActionDescriptorProvider service as a poor way to test this.
95-
services.TryAddEnumerable(
96-
ServiceDescriptor.Singleton<IActionDescriptorProvider, PageActionDescriptorProvider>());
96+
services.TryAddEnumerable(
97+
ServiceDescriptor.Singleton<IActionDescriptorProvider, PageActionDescriptorProvider>());
9798

98-
services.TryAddEnumerable(ServiceDescriptor.Singleton<MatcherPolicy, PageLoaderMatcherPolicy>());
99-
}
99+
services.TryAddEnumerable(ServiceDescriptor.Singleton<MatcherPolicy, PageLoaderMatcherPolicy>());
100100

101101
services.TryAddSingleton<RuntimeCompilationFileProvider>();
102102
services.TryAddSingleton<RazorReferenceManager>();

src/Mvc/Mvc.Razor.RuntimeCompilation/src/PageLoaderMatcherPolicy.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,27 @@
77
using Microsoft.AspNetCore.Http;
88
using Microsoft.AspNetCore.Routing;
99
using Microsoft.AspNetCore.Routing.Matching;
10+
using Microsoft.Extensions.DependencyInjection;
1011

1112
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
1213
{
1314
internal class PageLoaderMatcherPolicy : MatcherPolicy, IEndpointSelectorPolicy
1415
{
15-
private readonly PageLoader _loader;
16-
17-
public PageLoaderMatcherPolicy(PageLoader loader)
16+
private PageLoader? _loader;
17+
18+
/// <remarks>
19+
/// The <see cref="PageLoader"/> service is configured by <c>app.AddRazorPages()</c>.
20+
/// If the app is configured as <c>app.AddControllersWithViews().AddRazorRuntimeCompilation()</c>, the <see cref="PageLoader"/>
21+
/// service will not be registered. Since Razor Pages is not a pre-req for runtime compilation, we'll defer reading the service
22+
/// until we need to load a page in the body of <see cref="ApplyAsync(HttpContext, CandidateSet)"/>.
23+
/// </remarks>
24+
public PageLoaderMatcherPolicy()
25+
: this(loader: null)
1826
{
19-
if (loader == null)
20-
{
21-
throw new ArgumentNullException(nameof(loader));
22-
}
27+
}
2328

29+
public PageLoaderMatcherPolicy(PageLoader? loader)
30+
{
2431
_loader = loader;
2532
}
2633

@@ -76,6 +83,8 @@ public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates)
7683
var page = endpoint.Metadata.GetMetadata<PageActionDescriptor>();
7784
if (page != null)
7885
{
86+
_loader ??= httpContext.RequestServices.GetRequiredService<PageLoader>();
87+
7988
// We found an endpoint instance that has a PageActionDescriptor, but not a
8089
// CompiledPageActionDescriptor. Update the CandidateSet.
8190
var compiled = _loader.LoadAsync(page, endpoint.Metadata);
@@ -88,15 +97,15 @@ public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates)
8897
{
8998
// In the most common case, GetOrAddAsync will return a synchronous result.
9099
// Avoid going async since this is a fairly hot path.
91-
return ApplyAsyncAwaited(candidates, compiled, i);
100+
return ApplyAsyncAwaited(_loader, candidates, compiled, i);
92101
}
93102
}
94103
}
95104

96105
return Task.CompletedTask;
97106
}
98107

99-
private async Task ApplyAsyncAwaited(CandidateSet candidates, Task<CompiledPageActionDescriptor> actionDescriptorTask, int index)
108+
private static async Task ApplyAsyncAwaited(PageLoader pageLoader, CandidateSet candidates, Task<CompiledPageActionDescriptor> actionDescriptorTask, int index)
100109
{
101110
var compiled = await actionDescriptorTask;
102111

@@ -115,7 +124,7 @@ private async Task ApplyAsyncAwaited(CandidateSet candidates, Task<CompiledPageA
115124
var page = endpoint.Metadata.GetMetadata<PageActionDescriptor>();
116125
if (page != null)
117126
{
118-
compiled = await _loader.LoadAsync(page, endpoint.Metadata);
127+
compiled = await pageLoader.LoadAsync(page, endpoint.Metadata);
119128

120129
candidates.ReplaceEndpoint(i, compiled.Endpoint, candidates[i].Values);
121130
}

src/Mvc/Mvc.Razor.RuntimeCompilation/test/DependencyInjection/RazorRuntimeCompilationMvcCoreBuilderExtensionsTest.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,5 @@ public void AddServices_ReplacesActionDescriptorProvider()
4545
serviceDescriptor = Assert.Single(services, service => service.ServiceType == typeof(MatcherPolicy));
4646
Assert.Equal(typeof(PageLoaderMatcherPolicy), serviceDescriptor.ImplementationType);
4747
}
48-
49-
[Fact]
50-
public void AddServices_DoesNotPageActionDescriptor_IfItWasNotPreviouslyFound()
51-
{
52-
// we want to make sure Page specific featurees are only added if AddRazorPages was called by the user.
53-
// Arrange
54-
var services = new ServiceCollection();
55-
56-
// Act
57-
RazorRuntimeCompilationMvcCoreBuilderExtensions.AddServices(services);
58-
59-
// Assert
60-
Assert.Empty(services.Where(service => service.ServiceType == typeof(IActionDescriptorProvider)));
61-
Assert.Empty(services.Where(service => service.ServiceType == typeof(MatcherPolicy)));
62-
}
6348
}
6449
}

src/Mvc/Mvc.Razor.RuntimeCompilation/test/PageLoaderMatcherPolicyTest.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Microsoft.AspNetCore.Mvc.Abstractions;
99
using Microsoft.AspNetCore.Routing;
1010
using Microsoft.AspNetCore.Routing.Matching;
11+
using Microsoft.Extensions.DependencyInjection;
1112
using Moq;
1213
using Xunit;
1314

@@ -34,6 +35,32 @@ public async Task ApplyAsync_UpdatesCandidateSet()
3435
Assert.Same(compiled.Endpoint, candidateSet[0].Endpoint);
3536
}
3637

38+
[Fact]
39+
public async Task ApplyAsync_ReadsLoaderFromRequestServices()
40+
{
41+
// Arrange
42+
var compiled = new CompiledPageActionDescriptor();
43+
compiled.Endpoint = CreateEndpoint(new PageActionDescriptor());
44+
45+
var candidateSet = CreateCandidateSet(compiled);
46+
var loader = new Mock<PageLoader>();
47+
loader.Setup(l => l.LoadAsync(It.IsAny<PageActionDescriptor>(), It.IsAny<EndpointMetadataCollection>()))
48+
.Returns(Task.FromResult(compiled))
49+
.Verifiable();
50+
var policy = new PageLoaderMatcherPolicy();
51+
var httpContext = new DefaultHttpContext
52+
{
53+
RequestServices = new ServiceCollection().AddSingleton(loader.Object).BuildServiceProvider(),
54+
};
55+
56+
// Act
57+
await policy.ApplyAsync(httpContext, candidateSet);
58+
59+
// Assert
60+
Assert.Same(compiled.Endpoint, candidateSet[0].Endpoint);
61+
loader.Verify();
62+
}
63+
3764
[Fact]
3865
public async Task ApplyAsync_UpdatesCandidateSet_IfLoaderReturnsAsynchronously()
3966
{

src/Mvc/Mvc.RazorPages/src/DependencyInjection/MvcRazorPagesMvcCoreBuilderExtensions.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5+
using System.Linq;
56
using Microsoft.AspNetCore.Mvc.Abstractions;
67
using Microsoft.AspNetCore.Mvc.ApplicationModels;
78
using Microsoft.AspNetCore.Mvc.Filters;
@@ -107,8 +108,19 @@ internal static void AddRazorPagesServices(IServiceCollection services)
107108
services.TryAddSingleton<PageActionEndpointDataSourceIdProvider>();
108109

109110
// Action description and invocation
110-
services.TryAddEnumerable(
111-
ServiceDescriptor.Singleton<IActionDescriptorProvider, CompiledPageActionDescriptorProvider>());
111+
var actionDescriptorProvider = services.FirstOrDefault(f =>
112+
f.ServiceType == typeof(IActionDescriptorProvider) &&
113+
f.ImplementationType == typeof(PageActionDescriptorProvider));
114+
115+
if (actionDescriptorProvider is null)
116+
{
117+
// RuntimeCompilation registers an instance of PageActionDescriptorProvider (PageADP). CompiledPageADP and runtime compilation
118+
// cannot co-exist since CompiledPageADP will attempt to resolve action descriptors for lazily compiled views (such as for
119+
// ones from non-physical file providers). We'll instead avoid adding it if PageADP is already registered. Similarly,
120+
// AddRazorRuntimeCompilation will remove CompiledPageADP if it is registered.
121+
services.TryAddEnumerable(
122+
ServiceDescriptor.Singleton<IActionDescriptorProvider, CompiledPageActionDescriptorProvider>());
123+
}
112124
services.TryAddEnumerable(
113125
ServiceDescriptor.Singleton<IPageRouteModelProvider, CompiledPageRouteModelProvider>());
114126
services.TryAddSingleton<PageActionEndpointDataSourceFactory>();

src/Mvc/Mvc.RazorPages/src/RazorPagesOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class RazorPagesOptions : IEnumerable<ICompatibilitySwitch>
2121
/// Gets a collection of <see cref="IPageConvention"/> instances that are applied during
2222
/// route and page model construction.
2323
/// </summary>
24-
public PageConventionCollection Conventions { get; internal set; } = default!;
24+
public PageConventionCollection Conventions { get; internal set; } = new();
2525

2626
/// <summary>
2727
/// Application relative path used as the root of discovery for Razor Page files.

src/Mvc/Mvc.slnf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"src\\DataProtection\\DataProtection\\src\\Microsoft.AspNetCore.DataProtection.csproj",
1414
"src\\DataProtection\\Extensions\\src\\Microsoft.AspNetCore.DataProtection.Extensions.csproj",
1515
"src\\DefaultBuilder\\src\\Microsoft.AspNetCore.csproj",
16+
"src\\Extensions\\Features\\src\\Microsoft.Extensions.Features.csproj",
1617
"src\\Features\\JsonPatch\\src\\Microsoft.AspNetCore.JsonPatch.csproj",
1718
"src\\FileProviders\\Embedded\\src\\Microsoft.Extensions.FileProviders.Embedded.csproj",
1819
"src\\FileProviders\\Manifest.MSBuildTask\\src\\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.csproj",
@@ -24,7 +25,6 @@
2425
"src\\Html.Abstractions\\src\\Microsoft.AspNetCore.Html.Abstractions.csproj",
2526
"src\\Http\\Authentication.Abstractions\\src\\Microsoft.AspNetCore.Authentication.Abstractions.csproj",
2627
"src\\Http\\Authentication.Core\\src\\Microsoft.AspNetCore.Authentication.Core.csproj",
27-
"src\\Extensions\\Features\\src\\Microsoft.Extensions.Features.csproj",
2828
"src\\Http\\Headers\\src\\Microsoft.Net.Http.Headers.csproj",
2929
"src\\Http\\Http.Abstractions\\src\\Microsoft.AspNetCore.Http.Abstractions.csproj",
3030
"src\\Http\\Http.Extensions\\src\\Microsoft.AspNetCore.Http.Extensions.csproj",
@@ -133,6 +133,7 @@
133133
"src\\Servers\\IIS\\IIS\\src\\Microsoft.AspNetCore.Server.IIS.csproj",
134134
"src\\Servers\\Kestrel\\Core\\src\\Microsoft.AspNetCore.Server.Kestrel.Core.csproj",
135135
"src\\Servers\\Kestrel\\Kestrel\\src\\Microsoft.AspNetCore.Server.Kestrel.csproj",
136+
"src\\Servers\\Kestrel\\Transport.Quic\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.csproj",
136137
"src\\Servers\\Kestrel\\Transport.Sockets\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj",
137138
"src\\SignalR\\common\\Http.Connections.Common\\src\\Microsoft.AspNetCore.Http.Connections.Common.csproj",
138139
"src\\SignalR\\common\\Http.Connections\\src\\Microsoft.AspNetCore.Http.Connections.csproj",

0 commit comments

Comments
 (0)