Skip to content

Commit 08072a8

Browse files
captainsafiadougbu
andauthored
[release/6.0] Add support for minimal APIs in ApiDescription.Server (#44227)
* [release/6.0] Add support for minimal APIs in ApiDescription.Server * [release/7.0] Quarantine `ClosingTheBrowserWindow_GracefullyDisconnects_TheCurrentCircuit` (#44186) - #44185 - also upload test logs for forks * Update CircuitGracefulTerminationTests.cs Co-authored-by: Doug Bunting <[email protected]>
1 parent ed77238 commit 08072a8

File tree

9 files changed

+139
-13
lines changed

9 files changed

+139
-13
lines changed

.azure/pipelines/components-e2e-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,5 @@ jobs:
7575
artifacts:
7676
- name: Components_E2E_Test_Logs
7777
path: '$(Build.SourcesDirectory)/artifacts/TestResults/$(BuildConfiguration)'
78+
includeForks: true
7879
publishOnError: true

src/Components/test/E2ETest/ServerExecutionTests/CircuitGracefulTerminationTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
using BasicTestApp;
88
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
99
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
10-
using Microsoft.AspNetCore.Testing;
1110
using Microsoft.AspNetCore.E2ETesting;
11+
using Microsoft.AspNetCore.Testing;
1212
using Microsoft.Extensions.DependencyInjection;
1313
using Microsoft.Extensions.Logging.Testing;
1414
using OpenQA.Selenium;
@@ -66,6 +66,7 @@ public async Task ReloadingThePage_GracefullyDisconnects_TheCurrentCircuit()
6666
}
6767

6868
[Fact]
69+
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/44185")]
6970
public async Task ClosingTheBrowserWindow_GracefullyDisconnects_TheCurrentCircuit()
7071
{
7172
// Arrange & Act

src/Tools/Extensions.ApiDescription.Server/src/Microsoft.Extensions.ApiDescription.Server.csproj

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
<PropertyGroup>
55
<!-- Included primarily to ensure dotnet-getdocument and GetDocument.Insider can be referenced. -->
6-
<TargetFrameworks>netcoreapp2.1;$(DefaultNetFxTargetFramework)</TargetFrameworks>
6+
<TargetFrameworks>netcoreapp2.1;$(DefaultNetCoreTargetFramework);$(DefaultNetFxTargetFramework)</TargetFrameworks>
77

88
<Description>MSBuild tasks and targets for build-time Swagger and OpenApi document generation</Description>
99
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
@@ -19,12 +19,16 @@
1919
because publish output matches what was built.
2020
-->
2121
<Reference Include="dotnet-getdocument"
22-
Targets="Publish"
23-
ReferenceOutputAssembly="false"
24-
SkipGetTargetFrameworkProperties="true"
25-
UndefineProperties="TargetFramework;TargetFrameworks;RuntimeIdentifier;PublishDir" />
26-
<Reference Include="GetDocument.Insider" ReferenceOutputAssembly="false">
27-
<Targets Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">Publish</Targets>
22+
Condition=" '$(TargetFramework)' != '$(DefaultNetFxTargetFramework)' "
23+
Targets="Publish"
24+
Private="false"
25+
ReferenceOutputAssembly="false"
26+
SkipGetTargetFrameworkProperties="true" />
27+
<Reference Include="GetDocument.Insider"
28+
Private="false"
29+
ReferenceOutputAssembly="false"
30+
SkipGetTargetFrameworkProperties="true">
31+
<Targets Condition=" '$(TargetFramework)' != '$(DefaultNetFxTargetFramework)' ">Publish</Targets>
2832
</Reference>
2933
</ItemGroup>
3034

src/Tools/Extensions.ApiDescription.Server/src/Microsoft.Extensions.ApiDescription.Server.nuspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
<file src="$artifactsBinDir$\GetDocument.Insider\$configuration$\net461\*.*" target="tools\net461" />
1313
<file src="$artifactsBinDir$\GetDocument.Insider\x86\$configuration$\net461\*.*" target="tools\net461-x86" />
1414
<file src="$artifactsBinDir$\GetDocument.Insider\$configuration$\netcoreapp2.1\publish\*.*" target="tools\netcoreapp2.1" />
15+
<file src="$artifactsBinDir$\GetDocument.Insider\$configuration$\net6.0\publish\*.*" target="tools\net6.0" />
1516
</files>
1617
</package>

src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using System.IO;
66
using System.Linq;
77
using System.Reflection;
8-
#if NETCOREAPP2_1
8+
#if NETCOREAPP
99
using System.Runtime.Loader;
1010
#endif
1111
using Microsoft.Extensions.CommandLineUtils;
@@ -69,7 +69,7 @@ protected override int Execute()
6969
}
7070
}
7171

72-
#if NETCOREAPP2_1
72+
#if NETCOREAPP
7373
AssemblyLoadContext.Default.Resolving += (loadContext, assemblyName) =>
7474
{
7575
var name = assemblyName.Name;

src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandWorker.cs

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

44
using System;
5+
using System.Collections;
56
using System.Collections.Generic;
67
using System.IO;
78
using System.Reflection;
89
using System.Text;
10+
using System.Threading;
911
using System.Threading.Tasks;
1012
using Microsoft.Extensions.Hosting;
1113
using Microsoft.Extensions.Tools.Internal;
14+
#if NET6_0_OR_GREATER
15+
using Microsoft.AspNetCore.Hosting.Server;
16+
using Microsoft.Extensions.DependencyInjection;
17+
using Microsoft.AspNetCore.Http.Features;
18+
#endif
1219

1320
namespace Microsoft.Extensions.ApiDescription.Tool.Commands
1421
{
@@ -53,6 +60,88 @@ public int Process()
5360
return 3;
5461
}
5562

63+
#if NET6_0_OR_GREATER
64+
// Register no-op implementations of IServer and IHostLifetime
65+
// to prevent the application server from actually launching after build.
66+
void ConfigureHostBuilder(object hostBuilder)
67+
{
68+
((IHostBuilder)hostBuilder).ConfigureServices((context, services) =>
69+
{
70+
services.AddSingleton<IServer, NoopServer>();
71+
services.AddSingleton<IHostLifetime, NoopHostLifetime>();
72+
});
73+
}
74+
75+
// Register a TCS to be invoked when the entrypoint (aka Program.Main)
76+
// has finished running. For minimal APIs, this means that all app.X
77+
// calls about the host has been built have been executed.
78+
var waitForStartTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
79+
void OnEntryPointExit(Exception exception)
80+
{
81+
// If the entry point exited, we'll try to complete the wait
82+
if (exception != null)
83+
{
84+
waitForStartTcs.TrySetException(exception);
85+
}
86+
else
87+
{
88+
waitForStartTcs.TrySetResult(null);
89+
}
90+
}
91+
92+
// Resolve the host factory, ensuring that we don't stop the
93+
// application after the host has been built.
94+
var factory = HostFactoryResolver.ResolveHostFactory(assembly,
95+
stopApplication: false,
96+
configureHostBuilder: ConfigureHostBuilder,
97+
entrypointCompleted: OnEntryPointExit);
98+
99+
if (factory == null)
100+
{
101+
_reporter.WriteError(Resources.FormatMethodsNotFound(
102+
HostFactoryResolver.BuildWebHost,
103+
HostFactoryResolver.CreateHostBuilder,
104+
HostFactoryResolver.CreateWebHostBuilder,
105+
entryPointType));
106+
107+
return 8;
108+
}
109+
110+
try
111+
{
112+
// Retrieve the service provider from the target host.
113+
var services = ((IHost)factory(new[] { $"--{HostDefaults.ApplicationKey}={assemblyName}" })).Services;
114+
if (services == null)
115+
{
116+
_reporter.WriteError(Resources.FormatServiceProviderNotFound(
117+
typeof(IServiceProvider),
118+
HostFactoryResolver.BuildWebHost,
119+
HostFactoryResolver.CreateHostBuilder,
120+
HostFactoryResolver.CreateWebHostBuilder,
121+
entryPointType));
122+
123+
return 9;
124+
}
125+
126+
// Wait for the application to start to ensure that all configurations
127+
// on the WebApplicationBuilder have been processed.
128+
var applicationLifetime = services.GetRequiredService<IHostApplicationLifetime>();
129+
using (var registration = applicationLifetime.ApplicationStarted.Register(() => waitForStartTcs.TrySetResult(null)))
130+
{
131+
waitForStartTcs.Task.Wait();
132+
var success = GetDocuments(services);
133+
if (!success)
134+
{
135+
return 10;
136+
}
137+
}
138+
}
139+
catch (Exception ex)
140+
{
141+
_reporter.WriteError(ex.ToString());
142+
return 11;
143+
}
144+
#else
56145
try
57146
{
58147
var serviceFactory = HostFactoryResolver.ResolveServiceProviderFactory(assembly);
@@ -91,6 +180,7 @@ public int Process()
91180
_reporter.WriteError(ex.ToString());
92181
return 7;
93182
}
183+
#endif
94184

95185
return 0;
96186
}
@@ -303,5 +393,22 @@ private object InvokeMethod(MethodInfo method, object instance, object[] argumen
303393

304394
return result;
305395
}
396+
397+
#if NET6_0_OR_GREATER
398+
private sealed class NoopHostLifetime : IHostLifetime
399+
{
400+
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
401+
public Task WaitForStartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
402+
}
403+
404+
private sealed class NoopServer : IServer
405+
{
406+
public IFeatureCollection Features { get; } = new FeatureCollection();
407+
public void Dispose() { }
408+
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken) => Task.CompletedTask;
409+
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
410+
411+
}
412+
#endif
306413
}
307414
}

src/Tools/GetDocumentInsider/src/GetDocument.Insider.csproj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@
55
<IsPackable>false</IsPackable>
66
<OutputType>Exe</OutputType>
77
<RootNamespace>Microsoft.Extensions.ApiDescription.Tool</RootNamespace>
8-
<TargetFrameworks>netcoreapp2.1;$(DefaultNetFxTargetFramework)</TargetFrameworks>
8+
<TargetFrameworks>netcoreapp2.1;$(DefaultNetCoreTargetFramework);$(DefaultNetFxTargetFramework)</TargetFrameworks>
99
<IsShippingPackage>false</IsShippingPackage>
1010
</PropertyGroup>
1111

1212
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetFxTargetFramework)'">
1313
<Reference Include="Microsoft.CSharp" />
1414
</ItemGroup>
1515

16+
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
17+
<Reference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" />
18+
<Reference Include="Microsoft.Extensions.Hosting.Abstractions" />
19+
</ItemGroup>
20+
1621
<ItemGroup>
1722
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.6.0">
1823
<AllowExplicitReference>true</AllowExplicitReference>

src/Tools/dotnet-getdocument/src/Commands/InvokeCommand.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,16 @@ protected override int Execute()
7979
projectName,
8080
targetFramework.Version));
8181
}
82+
else if (targetFramework.Version >= new Version(6, 0))
83+
{
84+
toolsDirectory = Path.Combine(thisPath, $"net{targetFramework.Version}");
85+
}
86+
else
87+
{
88+
toolsDirectory = Path.Combine(thisPath, "netcoreapp2.1");
89+
}
8290

8391
executable = DotNetMuxer.MuxerPathOrDefault();
84-
toolsDirectory = Path.Combine(thisPath, "netcoreapp2.1");
8592

8693
args.Add("exec");
8794
args.Add("--depsFile");

src/Tools/dotnet-getdocument/src/dotnet-getdocument.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<IsPackable>false</IsPackable>
66
<OutputType>Exe</OutputType>
77
<RootNamespace>Microsoft.Extensions.ApiDescription.Tool</RootNamespace>
8-
<TargetFramework>netcoreapp2.1</TargetFramework>
8+
<TargetFrameworks>netcoreapp2.1;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
99
<UseAppHost>false</UseAppHost>
1010
<IsShippingPackage>false</IsShippingPackage>
1111
</PropertyGroup>

0 commit comments

Comments
 (0)