From f2c3c11a2d5cc6006b2dd79b686c3057fefc1ae6 Mon Sep 17 00:00:00 2001 From: ar0311 Date: Tue, 25 Aug 2020 08:51:09 +1000 Subject: [PATCH 01/26] Minor typos (#25140) --- .../Server/Controllers/WeatherForecastController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Controllers/WeatherForecastController.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Controllers/WeatherForecastController.cs index 15f1df532a52..99971dfae8e5 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Controllers/WeatherForecastController.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Controllers/WeatherForecastController.cs @@ -37,7 +37,7 @@ public class WeatherForecastController : ControllerBase private readonly ILogger _logger; - // The Web API will only accept tokens 1) for users, and 2) having the access_as_user scope for this API + // The Web API will only accept tokens 1) for users, and 2) having the api-scope scope for this API static readonly string[] scopeRequiredByApi = new string[] { "api-scope" }; #if (GenerateApi) @@ -75,7 +75,7 @@ public WeatherForecastController(ILogger logger, { _logger = logger; _graphServiceClient = graphServiceClient; - } + } [HttpGet] public async Task> Get() From db77380c84b3b0e62c25945d6703a74c16b192d0 Mon Sep 17 00:00:00 2001 From: Brennan Date: Mon, 24 Aug 2020 16:45:33 -0700 Subject: [PATCH 02/26] Java client connection state part 1 (#24166) --- .../com/microsoft/signalr/HubConnection.java | 149 ++++++++++-------- .../microsoft/signalr/HubConnectionState.java | 1 + .../microsoft/signalr/HubConnectionTest.java | 44 ++++-- .../com/microsoft/signalr/sample/Chat.java | 3 +- 4 files changed, 119 insertions(+), 78 deletions(-) diff --git a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java index 12349152dc1e..b0bcbb364829 100644 --- a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java +++ b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java @@ -66,6 +66,7 @@ public class HubConnection implements AutoCloseable { private final int negotiateVersion = 1; private final Logger logger = LoggerFactory.getLogger(HubConnection.class); private ScheduledExecutorService handshakeTimeout = null; + private Completable start; /** * Sets the server timeout interval for the connection. @@ -341,83 +342,99 @@ public void setBaseUrl(String url) { * @return A Completable that completes when the connection has been established. */ public Completable start() { - if (hubConnectionState != HubConnectionState.DISCONNECTED) { - return Completable.complete(); - } - - handshakeResponseSubject = CompletableSubject.create(); - handshakeReceived = false; - CompletableSubject tokenCompletable = CompletableSubject.create(); - localHeaders.put(UserAgentHelper.getUserAgentName(), UserAgentHelper.createUserAgentString()); - if (headers != null) { - this.localHeaders.putAll(headers); - } + CompletableSubject localStart = CompletableSubject.create(); - accessTokenProvider.subscribe(token -> { - if (token != null && !token.isEmpty()) { - this.localHeaders.put("Authorization", "Bearer " + token); + hubConnectionStateLock.lock(); + try { + if (hubConnectionState != HubConnectionState.DISCONNECTED) { + logger.debug("The connection is in the '{}' state. Waiting for in-progress start to complete or completing this start immediately.", hubConnectionState); + return start; } - tokenCompletable.onComplete(); - }, error -> { - tokenCompletable.onError(error); - }); - stopError = null; - Single negotiate = null; - if (!skipNegotiate) { - negotiate = tokenCompletable.andThen(Single.defer(() -> startNegotiate(baseUrl, 0))); - } else { - negotiate = tokenCompletable.andThen(Single.defer(() -> Single.just(new NegotiateResponse(baseUrl)))); - } + hubConnectionState = HubConnectionState.CONNECTING; + start = localStart; - CompletableSubject start = CompletableSubject.create(); + handshakeResponseSubject = CompletableSubject.create(); + handshakeReceived = false; + CompletableSubject tokenCompletable = CompletableSubject.create(); + localHeaders.put(UserAgentHelper.getUserAgentName(), UserAgentHelper.createUserAgentString()); + if (headers != null) { + this.localHeaders.putAll(headers); + } - negotiate.flatMapCompletable(negotiateResponse -> { - logger.debug("Starting HubConnection."); - if (transport == null) { - Single tokenProvider = negotiateResponse.getAccessToken() != null ? Single.just(negotiateResponse.getAccessToken()) : accessTokenProvider; - switch (transportEnum) { - case LONG_POLLING: - transport = new LongPollingTransport(localHeaders, httpClient, tokenProvider); - break; - default: - transport = new WebSocketTransport(localHeaders, httpClient); + accessTokenProvider.subscribe(token -> { + if (token != null && !token.isEmpty()) { + this.localHeaders.put("Authorization", "Bearer " + token); } + tokenCompletable.onComplete(); + }, error -> { + tokenCompletable.onError(error); + }); + + stopError = null; + Single negotiate = null; + if (!skipNegotiate) { + negotiate = tokenCompletable.andThen(Single.defer(() -> startNegotiate(baseUrl, 0))); + } else { + negotiate = tokenCompletable.andThen(Single.defer(() -> Single.just(new NegotiateResponse(baseUrl)))); } - transport.setOnReceive(this.callback); - transport.setOnClose((message) -> stopConnection(message)); - - return transport.start(negotiateResponse.getFinalUrl()).andThen(Completable.defer(() -> { - ByteBuffer handshake = HandshakeProtocol.createHandshakeRequestMessage( - new HandshakeRequestMessage(protocol.getName(), protocol.getVersion())); - - connectionState = new ConnectionState(this); - - return transport.send(handshake).andThen(Completable.defer(() -> { - timeoutHandshakeResponse(handshakeResponseTimeout, TimeUnit.MILLISECONDS); - return handshakeResponseSubject.andThen(Completable.defer(() -> { - hubConnectionStateLock.lock(); - try { - hubConnectionState = HubConnectionState.CONNECTED; - logger.info("HubConnection started."); - resetServerTimeout(); - //Don't send pings if we're using long polling. - if (transportEnum != TransportEnum.LONG_POLLING) { - activatePingTimer(); + negotiate.flatMapCompletable(negotiateResponse -> { + logger.debug("Starting HubConnection."); + if (transport == null) { + Single tokenProvider = negotiateResponse.getAccessToken() != null ? Single.just(negotiateResponse.getAccessToken()) : accessTokenProvider; + switch (transportEnum) { + case LONG_POLLING: + transport = new LongPollingTransport(localHeaders, httpClient, tokenProvider); + break; + default: + transport = new WebSocketTransport(localHeaders, httpClient); + } + } + + transport.setOnReceive(this.callback); + transport.setOnClose((message) -> stopConnection(message)); + + return transport.start(negotiateResponse.getFinalUrl()).andThen(Completable.defer(() -> { + ByteBuffer handshake = HandshakeProtocol.createHandshakeRequestMessage( + new HandshakeRequestMessage(protocol.getName(), protocol.getVersion())); + + connectionState = new ConnectionState(this); + + return transport.send(handshake).andThen(Completable.defer(() -> { + timeoutHandshakeResponse(handshakeResponseTimeout, TimeUnit.MILLISECONDS); + return handshakeResponseSubject.andThen(Completable.defer(() -> { + hubConnectionStateLock.lock(); + try { + hubConnectionState = HubConnectionState.CONNECTED; + logger.info("HubConnection started."); + resetServerTimeout(); + //Don't send pings if we're using long polling. + if (transportEnum != TransportEnum.LONG_POLLING) { + activatePingTimer(); + } + } finally { + hubConnectionStateLock.unlock(); } - } finally { - hubConnectionStateLock.unlock(); - } - return Completable.complete(); + return Completable.complete(); + })); })); })); - })); - // subscribe makes this a "hot" completable so this runs immediately - }).subscribeWith(start); + // subscribe makes this a "hot" completable so this runs immediately + }).subscribe(() -> { + localStart.onComplete(); + }, error -> { + hubConnectionStateLock.lock(); + hubConnectionState = HubConnectionState.DISCONNECTED; + hubConnectionStateLock.unlock(); + localStart.onError(error); + }); + } finally { + hubConnectionStateLock.unlock(); + } - return start; + return localStart; } private void activatePingTimer() { @@ -445,8 +462,8 @@ public void run() { } private Single startNegotiate(String url, int negotiateAttempts) { - if (hubConnectionState != HubConnectionState.DISCONNECTED) { - return Single.just(null); + if (hubConnectionState != HubConnectionState.CONNECTING) { + throw new RuntimeException("HubConnection trying to negotiate when not in the CONNECTING state."); } return handleNegotiate(url).flatMap(response -> { diff --git a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnectionState.java b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnectionState.java index a357946b6aec..d3fc796ee410 100644 --- a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnectionState.java +++ b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnectionState.java @@ -9,4 +9,5 @@ public enum HubConnectionState { CONNECTED, DISCONNECTED, + CONNECTING, } \ No newline at end of file diff --git a/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/HubConnectionTest.java b/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/HubConnectionTest.java index efee55e3ef3a..89b5a0efdd9e 100644 --- a/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/HubConnectionTest.java +++ b/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/HubConnectionTest.java @@ -24,6 +24,7 @@ import io.reactivex.Observable; import io.reactivex.Single; import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; import io.reactivex.subjects.CompletableSubject; import io.reactivex.subjects.PublishSubject; import io.reactivex.subjects.ReplaySubject; @@ -2577,9 +2578,10 @@ public void receiveHandshakeResponseAndMessage() { value.getAndUpdate((val) -> val + 1); }); + SingleSubject handshakeMessageTask = mockTransport.getNextSentMessage(); // On start we're going to receive the handshake response and also an invocation in the same payload. hubConnection.start(); - mockTransport.getStartTask().timeout(1, TimeUnit.SECONDS).blockingAwait(); + ByteBuffer sentMessage = handshakeMessageTask.timeout(1, TimeUnit.SECONDS).blockingGet(); String expectedSentMessage = "{\"protocol\":\"json\",\"version\":1}" + RECORD_SEPARATOR; assertEquals(expectedSentMessage, TestUtils.byteBufferToString(mockTransport.getSentMessages()[0])); @@ -2647,7 +2649,7 @@ public void hubConnectionClosesAndRunsOnClosedCallbackAfterCloseMessageWithError } @Test - public void callingStartOnStartedHubConnectionNoOps() { + public void callingStartOnStartedHubConnectionNoops() { HubConnection hubConnection = TestUtils.createHubConnection("http://example.com"); hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait(); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); @@ -2655,7 +2657,35 @@ public void callingStartOnStartedHubConnectionNoOps() { hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait(); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); - hubConnection.stop(); + hubConnection.stop().timeout(1, TimeUnit.SECONDS).blockingAwait(); + assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState()); + } + + @Test + public void callingStartOnStartingHubConnectionWaitsForOriginalStart() { + CompletableSubject startedAccessToken = CompletableSubject.create(); + CompletableSubject continueAccessToken = CompletableSubject.create(); + HubConnection hubConnection = HubConnectionBuilder.create("http://example.com") + .withTransportImplementation(new MockTransport(true)) + .withHttpClient(new TestHttpClient()) + .withAccessTokenProvider(Single.defer(() -> { + startedAccessToken.onComplete(); + continueAccessToken.timeout(1, TimeUnit.SECONDS).blockingAwait(); + return Single.just("test"); + }).subscribeOn(Schedulers.newThread())) + .shouldSkipNegotiate(true) + .build(); + Completable start = hubConnection.start(); + startedAccessToken.timeout(1, TimeUnit.SECONDS).blockingAwait(); + assertEquals(HubConnectionState.CONNECTING, hubConnection.getConnectionState()); + + Completable start2 = hubConnection.start(); + continueAccessToken.onComplete(); + start.timeout(1, TimeUnit.SECONDS).blockingAwait(); + start2.timeout(1, TimeUnit.SECONDS).blockingAwait(); + assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); + + hubConnection.stop().timeout(1, TimeUnit.SECONDS).blockingAwait(); assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState()); } @@ -3595,9 +3625,6 @@ public void userSetAuthHeaderIsNotClearedAfterRedirect() { assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); hubConnection.stop().blockingAwait(); assertEquals("ExampleValue", beforeRedirectHeader.get()); - - hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait(); - assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); assertEquals("Bearer redirectToken", afterRedirectHeader.get()); // Making sure you can do this after restarting the HubConnection. @@ -3605,9 +3632,6 @@ public void userSetAuthHeaderIsNotClearedAfterRedirect() { assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); hubConnection.stop().blockingAwait(); assertEquals("ExampleValue", beforeRedirectHeader.get()); - - hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait(); - assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); assertEquals("Bearer redirectToken", afterRedirectHeader.get()); } @@ -3699,7 +3723,7 @@ public void non200FromNegotiateThrowsError() { } @Test - public void hubConnectionCloseCallsStop() throws Exception { + public void hubConnectionCloseCallsStop() { MockTransport mockTransport = new MockTransport(); TestHttpClient client = new TestHttpClient() .on("POST", "http://example.com/negotiate?negotiateVersion=1", (req) -> Single.just(new HttpResponse(200, "", TestUtils.stringToByteBuffer("{\"url\":\"http://testexample.com/\"}")))) diff --git a/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/sample/Chat.java b/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/sample/Chat.java index d48c89818552..7a7ab4b8de8c 100644 --- a/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/sample/Chat.java +++ b/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/sample/Chat.java @@ -8,7 +8,6 @@ import com.microsoft.signalr.HubConnection; import com.microsoft.signalr.HubConnectionBuilder; - public class Chat { public static void main(final String[] args) throws Exception { System.out.println("Enter the URL of the SignalR Chat you want to join"); @@ -33,7 +32,7 @@ public static void main(final String[] args) throws Exception { while (!message.equals("leave")) { // Scans the next token of the input as an int. message = reader.nextLine(); - hubConnection.send("Send", message); + hubConnection.send("Send", "Java", message); } hubConnection.stop().blockingAwait(); From 29cbf6e1069d4f400a567f29a4becae47c45e9f3 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 24 Aug 2020 18:54:28 -0700 Subject: [PATCH 03/26] Make PropertySetter a concrete type (#25054) * Make PropertySetter a concrete type * Use the pattern from PropertyHelpers to set property values * Tweaks to Blazor WebAssembly tests to allow running tests locally * Update src/Components/Components/src/Reflection/IPropertySetter.cs --- .../Components/src/ComponentFactory.cs | 2 +- .../src/Reflection/ComponentProperties.cs | 21 ++++---- .../src/Reflection/IPropertySetter.cs | 49 +++++++++++++++++-- .../src/Reflection/MemberAssignment.cs | 41 ---------------- .../Wasm.Performance/Directory.Build.props | 11 +++++ .../Wasm.Performance/Driver/Program.cs | 32 +++++++++++- .../Wasm.Performance/Driver/Selenium.cs | 7 +-- .../TestApp/Wasm.Performance.TestApp.csproj | 5 ++ 8 files changed, 107 insertions(+), 61 deletions(-) create mode 100644 src/Components/benchmarkapps/Wasm.Performance/Directory.Build.props diff --git a/src/Components/Components/src/ComponentFactory.cs b/src/Components/Components/src/ComponentFactory.cs index eddb39a937bf..10c9b1aa06b6 100644 --- a/src/Components/Components/src/ComponentFactory.cs +++ b/src/Components/Components/src/ComponentFactory.cs @@ -63,7 +63,7 @@ private Action CreateInitializer(Type type) ( propertyName: property.Name, propertyType: property.PropertyType, - setter: MemberAssignment.CreatePropertySetter(type, property, cascading: false) + setter: new PropertySetter(type, property) )).ToArray(); return Initialize; diff --git a/src/Components/Components/src/Reflection/ComponentProperties.cs b/src/Components/Components/src/Reflection/ComponentProperties.cs index 1b6e43d7ba4e..dd6aafab26e2 100644 --- a/src/Components/Components/src/Reflection/ComponentProperties.cs +++ b/src/Components/Components/src/Reflection/ComponentProperties.cs @@ -144,7 +144,7 @@ public static void SetProperties(in ParameterView parameters, object target) } } - static void SetProperty(object target, IPropertySetter writer, string parameterName, object value) + static void SetProperty(object target, PropertySetter writer, string parameterName, object value) { try { @@ -246,13 +246,13 @@ private static void ThrowForInvalidCaptureUnmatchedValuesParameterType(Type targ private class WritersForType { private const int MaxCachedWriterLookups = 100; - private readonly Dictionary _underlyingWriters; - private readonly ConcurrentDictionary _referenceEqualityWritersCache; + private readonly Dictionary _underlyingWriters; + private readonly ConcurrentDictionary _referenceEqualityWritersCache; public WritersForType(Type targetType) { - _underlyingWriters = new Dictionary(StringComparer.OrdinalIgnoreCase); - _referenceEqualityWritersCache = new ConcurrentDictionary(ReferenceEqualityComparer.Instance); + _underlyingWriters = new Dictionary(StringComparer.OrdinalIgnoreCase); + _referenceEqualityWritersCache = new ConcurrentDictionary(ReferenceEqualityComparer.Instance); foreach (var propertyInfo in GetCandidateBindableProperties(targetType)) { @@ -271,7 +271,10 @@ public WritersForType(Type targetType) $"The type '{targetType.FullName}' declares a parameter matching the name '{propertyName}' that is not public. Parameters must be public."); } - var propertySetter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: cascadingParameterAttribute != null); + var propertySetter = new PropertySetter(targetType, propertyInfo) + { + Cascading = cascadingParameterAttribute != null, + }; if (_underlyingWriters.ContainsKey(propertyName)) { @@ -298,17 +301,17 @@ public WritersForType(Type targetType) ThrowForInvalidCaptureUnmatchedValuesParameterType(targetType, propertyInfo); } - CaptureUnmatchedValuesWriter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: false); + CaptureUnmatchedValuesWriter = new PropertySetter(targetType, propertyInfo); CaptureUnmatchedValuesPropertyName = propertyInfo.Name; } } } - public IPropertySetter? CaptureUnmatchedValuesWriter { get; } + public PropertySetter? CaptureUnmatchedValuesWriter { get; } public string? CaptureUnmatchedValuesPropertyName { get; } - public bool TryGetValue(string parameterName, [MaybeNullWhen(false)] out IPropertySetter writer) + public bool TryGetValue(string parameterName, [MaybeNullWhen(false)] out PropertySetter writer) { // In intensive parameter-passing scenarios, one of the most expensive things we do is the // lookup from parameterName to writer. Pre-5.0 that was because of the string hashing. diff --git a/src/Components/Components/src/Reflection/IPropertySetter.cs b/src/Components/Components/src/Reflection/IPropertySetter.cs index d6a60e2395ae..5cd1cb0494d5 100644 --- a/src/Components/Components/src/Reflection/IPropertySetter.cs +++ b/src/Components/Components/src/Reflection/IPropertySetter.cs @@ -1,12 +1,55 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Reflection; + namespace Microsoft.AspNetCore.Components.Reflection { - internal interface IPropertySetter + internal sealed class PropertySetter { - bool Cascading { get; } + private static readonly MethodInfo CallPropertySetterOpenGenericMethod = + typeof(PropertySetter).GetMethod(nameof(CallPropertySetter), BindingFlags.NonPublic | BindingFlags.Static)!; + + private readonly Action _setterDelegate; + + public PropertySetter(Type targetType, PropertyInfo property) + { + if (property.SetMethod == null) + { + throw new InvalidOperationException($"Cannot provide a value for property " + + $"'{property.Name}' on type '{targetType.FullName}' because the property " + + $"has no setter."); + } + + var setMethod = property.SetMethod; + + var propertySetterAsAction = + setMethod.CreateDelegate(typeof(Action<,>).MakeGenericType(targetType, property.PropertyType)); + var callPropertySetterClosedGenericMethod = + CallPropertySetterOpenGenericMethod.MakeGenericMethod(targetType, property.PropertyType); + _setterDelegate = (Action) + callPropertySetterClosedGenericMethod.CreateDelegate(typeof(Action), propertySetterAsAction); + } + + public bool Cascading { get; init; } + + public void SetValue(object target, object value) => _setterDelegate(target, value); - void SetValue(object target, object value); + private static void CallPropertySetter( + Action setter, + object target, + object value) + where TTarget : notnull + { + if (value == null) + { + setter((TTarget)target, default!); + } + else + { + setter((TTarget)target, (TValue)value); + } + } } } diff --git a/src/Components/Components/src/Reflection/MemberAssignment.cs b/src/Components/Components/src/Reflection/MemberAssignment.cs index 4510d4e81c36..1d0afbe49add 100644 --- a/src/Components/Components/src/Reflection/MemberAssignment.cs +++ b/src/Components/Components/src/Reflection/MemberAssignment.cs @@ -44,46 +44,5 @@ public static IEnumerable GetPropertiesIncludingInherited( return dictionary.Values.SelectMany(p => p); } - - public static IPropertySetter CreatePropertySetter(Type targetType, PropertyInfo property, bool cascading) - { - if (property.SetMethod == null) - { - throw new InvalidOperationException($"Cannot provide a value for property " + - $"'{property.Name}' on type '{targetType.FullName}' because the property " + - $"has no setter."); - } - - return (IPropertySetter)Activator.CreateInstance( - typeof(PropertySetter<,>).MakeGenericType(targetType, property.PropertyType), - property.SetMethod, - cascading)!; - } - - class PropertySetter : IPropertySetter where TTarget : notnull - { - private readonly Action _setterDelegate; - - public PropertySetter(MethodInfo setMethod, bool cascading) - { - _setterDelegate = (Action)Delegate.CreateDelegate( - typeof(Action), setMethod); - Cascading = cascading; - } - - public bool Cascading { get; } - - public void SetValue(object target, object value) - { - if (value == null) - { - _setterDelegate((TTarget)target, default!); - } - else - { - _setterDelegate((TTarget)target, (TValue)value); - } - } - } } } diff --git a/src/Components/benchmarkapps/Wasm.Performance/Directory.Build.props b/src/Components/benchmarkapps/Wasm.Performance/Directory.Build.props new file mode 100644 index 000000000000..0556b5271ed6 --- /dev/null +++ b/src/Components/benchmarkapps/Wasm.Performance/Directory.Build.props @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs index c3c3ae618fbf..c72ab9dccac4 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs @@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using OpenQA.Selenium; using DevHostServerProgram = Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server.Program; namespace Wasm.Performance.Driver @@ -81,7 +82,20 @@ public static async Task Main(string[] args) { BenchmarkResultTask = new TaskCompletionSource(); using var runCancellationToken = new CancellationTokenSource(timeForEachRun); - using var registration = runCancellationToken.Token.Register(() => BenchmarkResultTask.TrySetException(new TimeoutException($"Timed out after {timeForEachRun}"))); + using var registration = runCancellationToken.Token.Register(() => + { + string exceptionMessage = $"Timed out after {timeForEachRun}."; + try + { + var innerHtml = browser.FindElement(By.CssSelector(":first-child")).GetAttribute("innerHTML"); + exceptionMessage += Environment.NewLine + "Browser state: " + Environment.NewLine + innerHtml; + } + catch + { + // Do nothing; + } + BenchmarkResultTask.TrySetException(new TimeoutException(exceptionMessage)); + }); var results = await BenchmarkResultTask.Task; @@ -89,6 +103,11 @@ public static async Task Main(string[] args) includeMetadata: firstRun, isStressRun: isStressRun); + if (!isStressRun) + { + PrettyPrint(results); + } + firstRun = false; } while (isStressRun && !stressRunCancellation.IsCancellationRequested); @@ -230,6 +249,17 @@ private static void FormatAsBenchmarksOutput(BenchmarkResult benchmarkResult, bo Console.WriteLine(builder); } + static void PrettyPrint(BenchmarkResult benchmarkResult) + { + Console.WriteLine(); + Console.WriteLine("| Name | Description | Duration | NumExecutions | "); + Console.WriteLine("--------------------------"); + foreach (var result in benchmarkResult.ScenarioResults) + { + Console.WriteLine($"| {result.Descriptor.Name} | {result.Name} | {result.Duration} | {result.NumExecutions} |"); + } + } + static IHost StartTestApp() { var args = new[] diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs b/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs index f9d7ef47efa2..974854909960 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs @@ -16,12 +16,7 @@ class Selenium const int SeleniumPort = 4444; static bool RunHeadlessBrowser = true; - static bool PoolForBrowserLogs = -#if DEBUG - true; -#else - false; -#endif + static bool PoolForBrowserLogs = true; private static async ValueTask WaitForServerAsync(int port, CancellationToken cancellationToken) { diff --git a/src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj index d3e261a592e0..8157ceac2247 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj +++ b/src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj @@ -3,6 +3,11 @@ $(DefaultNetCoreTargetFramework) true + + false From 0050ece11808668c434adc5f498c872e1d58e115 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2020 03:36:26 +0000 Subject: [PATCH 04/26] [release/5.0] Update dependencies from dotnet/runtime dotnet/efcore (#25209) [release/5.0] Update dependencies from dotnet/runtime dotnet/efcore - Updates: - Microsoft.EntityFrameworkCore.Tools: from 5.0.0-rc.1.20424.8 to 5.0.0-rc.1.20424.9 - Microsoft.EntityFrameworkCore.SqlServer: from 5.0.0-rc.1.20424.8 to 5.0.0-rc.1.20424.9 - dotnet-ef: from 5.0.0-rc.1.20424.8 to 5.0.0-rc.1.20424.9 - Microsoft.EntityFrameworkCore: from 5.0.0-rc.1.20424.8 to 5.0.0-rc.1.20424.9 - Microsoft.EntityFrameworkCore.Design: from 5.0.0-rc.1.20424.8 to 5.0.0-rc.1.20424.9 - Microsoft.EntityFrameworkCore.Relational: from 5.0.0-rc.1.20424.8 to 5.0.0-rc.1.20424.9 - Microsoft.EntityFrameworkCore.Sqlite: from 5.0.0-rc.1.20424.8 to 5.0.0-rc.1.20424.9 - Microsoft.EntityFrameworkCore.InMemory: from 5.0.0-rc.1.20424.8 to 5.0.0-rc.1.20424.9 - Updates: - System.ComponentModel.Annotations: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Diagnostics.DiagnosticSource: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Diagnostics.EventLog: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Logging.Abstractions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Logging.Configuration: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Logging.Console: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Logging.Debug: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Logging.EventLog: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Logging.EventSource: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Logging.TraceSource: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Options: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Options.ConfigurationExtensions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Options.DataAnnotations: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Primitives: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Logging: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Internal.Transport: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Http: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Hosting.Abstractions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Caching.Abstractions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Caching.Memory: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.Abstractions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.Binder: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.CommandLine: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.EnvironmentVariables: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.FileExtensions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.Ini: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.UserSecrets: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.Xml: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.DependencyInjection: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.DependencyInjection.Abstractions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.DependencyModel: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.FileProviders.Abstractions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.FileProviders.Composite: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.FileProviders.Physical: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.FileSystemGlobbing: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.HostFactoryResolver.Sources: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Hosting: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Extensions.Configuration.Json: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.NETCore.App.Runtime.win-x64: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.NETCore.Platforms: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Win32.Registry: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.Win32.SystemEvents: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.NETCore.App.Internal: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - Microsoft.NETCore.App.Ref: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Drawing.Common: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Text.Json: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Threading.Channels: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Windows.Extensions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Text.Encodings.Web: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.ServiceProcess.ServiceController: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.IO.Pipelines: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Net.Http.Json: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Net.Http.WinHttpHandler: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Net.WebSockets.WebSocketProtocol: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Reflection.Metadata: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Resources.Extensions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Runtime.CompilerServices.Unsafe: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Security.AccessControl: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Security.Cryptography.Cng: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Security.Cryptography.Pkcs: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Security.Cryptography.Xml: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Security.Permissions: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 - System.Security.Principal.Windows: from 5.0.0-rc.1.20423.8 to 5.0.0-rc.1.20424.7 --- eng/Version.Details.xml | 288 ++++++++++++++++++++-------------------- eng/Versions.props | 144 ++++++++++---------- 2 files changed, 216 insertions(+), 216 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 22be0e0db714..94344cdd56b5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,301 +13,301 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 6dacc0d3c82451e7d4be989e57454c6c4377a099 + 7c6e244a2d012c522bce60c11597b4b2785b8254 - + https://github.com/dotnet/efcore - 6dacc0d3c82451e7d4be989e57454c6c4377a099 + 7c6e244a2d012c522bce60c11597b4b2785b8254 - + https://github.com/dotnet/efcore - 6dacc0d3c82451e7d4be989e57454c6c4377a099 + 7c6e244a2d012c522bce60c11597b4b2785b8254 - + https://github.com/dotnet/efcore - 6dacc0d3c82451e7d4be989e57454c6c4377a099 + 7c6e244a2d012c522bce60c11597b4b2785b8254 - + https://github.com/dotnet/efcore - 6dacc0d3c82451e7d4be989e57454c6c4377a099 + 7c6e244a2d012c522bce60c11597b4b2785b8254 - + https://github.com/dotnet/efcore - 6dacc0d3c82451e7d4be989e57454c6c4377a099 + 7c6e244a2d012c522bce60c11597b4b2785b8254 - + https://github.com/dotnet/efcore - 6dacc0d3c82451e7d4be989e57454c6c4377a099 + 7c6e244a2d012c522bce60c11597b4b2785b8254 - + https://github.com/dotnet/efcore - 6dacc0d3c82451e7d4be989e57454c6c4377a099 + 7c6e244a2d012c522bce60c11597b4b2785b8254 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 - + https://github.com/dotnet/runtime - 9aa4e069b5e9f6a33f7304fa7d58de26424588fb + 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index 5f2e1bb1ddc8..d4a2bff1715a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -64,83 +64,83 @@ 3.8.0-2.20407.3 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 - 5.0.0-rc.1.20423.8 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20423.8 + 5.0.0-rc.1.20424.7 3.2.0 - 5.0.0-rc.1.20424.1 - 5.0.0-rc.1.20424.1 - 5.0.0-rc.1.20424.1 - 5.0.0-rc.1.20424.1 - 5.0.0-rc.1.20424.1 - 5.0.0-rc.1.20424.1 - 5.0.0-rc.1.20424.1 - 5.0.0-rc.1.20424.1 + 5.0.0-rc.1.20424.9 + 5.0.0-rc.1.20424.9 + 5.0.0-rc.1.20424.9 + 5.0.0-rc.1.20424.9 + 5.0.0-rc.1.20424.9 + 5.0.0-rc.1.20424.9 + 5.0.0-rc.1.20424.9 + 5.0.0-rc.1.20424.9 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 - + https://github.com/dotnet/runtime - 5908e2b3ebf9259d41fc701f15d22dc6bd0959a2 + f43e0b670e180d9b6d9e674e08071aef5abc3cd6 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index d4a2bff1715a..bdc3ba84719f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -64,72 +64,72 @@ 3.8.0-2.20407.3 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 - 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.7 + 5.0.0-rc.1.20424.12 3.2.0 From e409c97612877b81bb4aa13433d8ff6e4ac78476 Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Mon, 24 Aug 2020 23:28:17 -0700 Subject: [PATCH 07/26] Allow suppressing the use of environment variables (#25136) * Allow suppressing the use of environment variables #20328 * Formatting * Update src/Hosting/Hosting/src/WebHostBuilderOptions.cs Co-authored-by: Kahbazi Co-authored-by: Kahbazi --- .../src/GenericHost/GenericWebHostBuilder.cs | 13 ++++-- .../GenericHostWebHostBuilderExtensions.cs | 33 ++++++++++++++- .../Hosting/src/WebHostBuilderOptions.cs | 17 ++++++++ .../Fakes/GenericWebHostBuilderWrapper.cs | 2 +- .../test/GenericWebHostBuilderTests.cs | 41 +++++++++++++++++++ .../Hosting/test/WebHostBuilderTests.cs | 4 -- 6 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 src/Hosting/Hosting/src/WebHostBuilderOptions.cs create mode 100644 src/Hosting/Hosting/test/GenericWebHostBuilderTests.cs diff --git a/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs b/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs index 9f97f03c4ef6..96f886e47446 100644 --- a/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs +++ b/src/Hosting/Hosting/src/GenericHost/GenericWebHostBuilder.cs @@ -29,13 +29,18 @@ internal class GenericWebHostBuilder : IWebHostBuilder, ISupportsStartup, ISuppo private AggregateException _hostingStartupErrors; private HostingStartupWebHostBuilder _hostingStartupWebHostBuilder; - public GenericWebHostBuilder(IHostBuilder builder) + public GenericWebHostBuilder(IHostBuilder builder, WebHostBuilderOptions options) { _builder = builder; + var configBuilder = new ConfigurationBuilder() + .AddInMemoryCollection(); - _config = new ConfigurationBuilder() - .AddEnvironmentVariables(prefix: "ASPNETCORE_") - .Build(); + if (!options.SuppressEnvironmentConfiguration) + { + configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_"); + } + + _config = configBuilder.Build(); _builder.ConfigureHostConfiguration(config => { diff --git a/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs b/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs index feb6da2ca4ba..4899a8caf2b5 100644 --- a/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs +++ b/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; @@ -6,9 +9,37 @@ namespace Microsoft.Extensions.Hosting { public static class GenericHostWebHostBuilderExtensions { + /// + /// Adds and configures an ASP.NET Core web application. + /// public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action configure) { - var webhostBuilder = new GenericWebHostBuilder(builder); + if (configure is null) + { + throw new ArgumentNullException(nameof(configure)); + } + + return builder.ConfigureWebHost(configure, _ => { }); + } + + /// + /// Adds and configures an ASP.NET Core web application. + /// + public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action configure, Action configureWebHostBuilder) + { + if (configure is null) + { + throw new ArgumentNullException(nameof(configure)); + } + + if (configureWebHostBuilder is null) + { + throw new ArgumentNullException(nameof(configureWebHostBuilder)); + } + + var webHostBuilderOptions = new WebHostBuilderOptions(); + configureWebHostBuilder(webHostBuilderOptions); + var webhostBuilder = new GenericWebHostBuilder(builder, webHostBuilderOptions); configure(webhostBuilder); builder.ConfigureServices((context, services) => services.AddHostedService()); return builder; diff --git a/src/Hosting/Hosting/src/WebHostBuilderOptions.cs b/src/Hosting/Hosting/src/WebHostBuilderOptions.cs new file mode 100644 index 000000000000..7fe6caef09e3 --- /dev/null +++ b/src/Hosting/Hosting/src/WebHostBuilderOptions.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.Hosting +{ + /// + /// Builder options for use with ConfigureWebHost. + /// + public class WebHostBuilderOptions + { + /// + /// Indicates if "ASPNETCORE_" prefixed environment variables should be added to configuration. + /// They are added by default. + /// + public bool SuppressEnvironmentConfiguration { get; set; } = false; + } +} diff --git a/src/Hosting/Hosting/test/Fakes/GenericWebHostBuilderWrapper.cs b/src/Hosting/Hosting/test/Fakes/GenericWebHostBuilderWrapper.cs index b0bf122d1b33..a8660bedd57e 100644 --- a/src/Hosting/Hosting/test/Fakes/GenericWebHostBuilderWrapper.cs +++ b/src/Hosting/Hosting/test/Fakes/GenericWebHostBuilderWrapper.cs @@ -16,7 +16,7 @@ public class GenericWebHostBuilderWrapper : IWebHostBuilder, ISupportsStartup, I internal GenericWebHostBuilderWrapper(HostBuilder hostBuilder) { - _builder = new GenericWebHostBuilder(hostBuilder); + _builder = new GenericWebHostBuilder(hostBuilder, new WebHostBuilderOptions()); _hostBuilder = hostBuilder; } diff --git a/src/Hosting/Hosting/test/GenericWebHostBuilderTests.cs b/src/Hosting/Hosting/test/GenericWebHostBuilderTests.cs new file mode 100644 index 000000000000..7ac55b1aecb3 --- /dev/null +++ b/src/Hosting/Hosting/test/GenericWebHostBuilderTests.cs @@ -0,0 +1,41 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Xunit; + +namespace Microsoft.AspNetCore.Hosting +{ + // Most functionality is covered by WebHostBuilderTests for compat. Only GenericHost specific functionality is covered here. + public class GenericWebHostBuilderTests + { + [Fact] + public void ReadsAspNetCoreEnvironmentVariables() + { + var randomEnvKey = Guid.NewGuid().ToString(); + Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, "true"); + using var host = new HostBuilder() + .ConfigureWebHost(_ => { }) + .Build(); + var config = host.Services.GetRequiredService(); + Assert.Equal("true", config[randomEnvKey]); + Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, null); + } + + [Fact] + public void CanSuppressAspNetCoreEnvironmentVariables() + { + var randomEnvKey = Guid.NewGuid().ToString(); + Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, "true"); + using var host = new HostBuilder() + .ConfigureWebHost(_ => { }, webHostBulderOptions => { webHostBulderOptions.SuppressEnvironmentConfiguration = true; }) + .Build(); + var config = host.Services.GetRequiredService(); + Assert.Null(config[randomEnvKey]); + Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, null); + } + } +} diff --git a/src/Hosting/Hosting/test/WebHostBuilderTests.cs b/src/Hosting/Hosting/test/WebHostBuilderTests.cs index d6b9a5f1a6dc..37ccbe5f21e3 100644 --- a/src/Hosting/Hosting/test/WebHostBuilderTests.cs +++ b/src/Hosting/Hosting/test/WebHostBuilderTests.cs @@ -6,19 +6,15 @@ using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; -using System.Web; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Fakes; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Tests.Fakes; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; From a01f9eb0ce63bae54f0fad2b3632702239bbae95 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2020 10:12:54 +0000 Subject: [PATCH 08/26] [release/5.0] Update dependencies from dotnet/efcore dotnet/runtime (#25226) [release/5.0] Update dependencies from dotnet/efcore dotnet/runtime - Updates: - Microsoft.EntityFrameworkCore.Tools: from 5.0.0-rc.1.20424.9 to 5.0.0-rc.1.20424.10 - Microsoft.EntityFrameworkCore.SqlServer: from 5.0.0-rc.1.20424.9 to 5.0.0-rc.1.20424.10 - dotnet-ef: from 5.0.0-rc.1.20424.9 to 5.0.0-rc.1.20424.10 - Microsoft.EntityFrameworkCore: from 5.0.0-rc.1.20424.9 to 5.0.0-rc.1.20424.10 - Microsoft.EntityFrameworkCore.Design: from 5.0.0-rc.1.20424.9 to 5.0.0-rc.1.20424.10 - Microsoft.EntityFrameworkCore.Relational: from 5.0.0-rc.1.20424.9 to 5.0.0-rc.1.20424.10 - Microsoft.EntityFrameworkCore.Sqlite: from 5.0.0-rc.1.20424.9 to 5.0.0-rc.1.20424.10 - Microsoft.EntityFrameworkCore.InMemory: from 5.0.0-rc.1.20424.9 to 5.0.0-rc.1.20424.10 - Updates: - System.ComponentModel.Annotations: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Diagnostics.DiagnosticSource: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Diagnostics.EventLog: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Logging.Abstractions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Logging.Configuration: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Logging.Console: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Logging.Debug: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Logging.EventLog: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Logging.EventSource: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Logging.TraceSource: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Options: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Options.ConfigurationExtensions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Options.DataAnnotations: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Primitives: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Logging: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Internal.Transport: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Http: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Hosting.Abstractions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Caching.Abstractions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Caching.Memory: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.Abstractions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.Binder: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.CommandLine: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.EnvironmentVariables: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.FileExtensions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.Ini: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.UserSecrets: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.Xml: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.DependencyInjection: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.DependencyInjection.Abstractions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.DependencyModel: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.FileProviders.Abstractions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.FileProviders.Composite: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.FileProviders.Physical: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.FileSystemGlobbing: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.HostFactoryResolver.Sources: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Hosting: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Extensions.Configuration.Json: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.NETCore.App.Runtime.win-x64: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.NETCore.Platforms: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Win32.Registry: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.Win32.SystemEvents: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.NETCore.App.Internal: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - Microsoft.NETCore.App.Ref: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Drawing.Common: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Text.Json: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Threading.Channels: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Windows.Extensions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Text.Encodings.Web: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.ServiceProcess.ServiceController: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.IO.Pipelines: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Net.Http.Json: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Net.Http.WinHttpHandler: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Net.WebSockets.WebSocketProtocol: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Reflection.Metadata: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Resources.Extensions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Runtime.CompilerServices.Unsafe: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Security.AccessControl: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Security.Cryptography.Cng: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Security.Cryptography.Pkcs: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Security.Cryptography.Xml: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Security.Permissions: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 - System.Security.Principal.Windows: from 5.0.0-rc.1.20424.12 to 5.0.0-rc.1.20424.16 --- eng/Version.Details.xml | 288 ++++++++++++++++++++-------------------- eng/Versions.props | 144 ++++++++++---------- 2 files changed, 216 insertions(+), 216 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 85d967e11de2..49ff63d451a2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,301 +13,301 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 7c6e244a2d012c522bce60c11597b4b2785b8254 + e3a2651ace8b707b59b8afa61ccb683a9d10646b - + https://github.com/dotnet/efcore - 7c6e244a2d012c522bce60c11597b4b2785b8254 + e3a2651ace8b707b59b8afa61ccb683a9d10646b - + https://github.com/dotnet/efcore - 7c6e244a2d012c522bce60c11597b4b2785b8254 + e3a2651ace8b707b59b8afa61ccb683a9d10646b - + https://github.com/dotnet/efcore - 7c6e244a2d012c522bce60c11597b4b2785b8254 + e3a2651ace8b707b59b8afa61ccb683a9d10646b - + https://github.com/dotnet/efcore - 7c6e244a2d012c522bce60c11597b4b2785b8254 + e3a2651ace8b707b59b8afa61ccb683a9d10646b - + https://github.com/dotnet/efcore - 7c6e244a2d012c522bce60c11597b4b2785b8254 + e3a2651ace8b707b59b8afa61ccb683a9d10646b - + https://github.com/dotnet/efcore - 7c6e244a2d012c522bce60c11597b4b2785b8254 + e3a2651ace8b707b59b8afa61ccb683a9d10646b - + https://github.com/dotnet/efcore - 7c6e244a2d012c522bce60c11597b4b2785b8254 + e3a2651ace8b707b59b8afa61ccb683a9d10646b - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be - + https://github.com/dotnet/runtime - f43e0b670e180d9b6d9e674e08071aef5abc3cd6 + 6db9bb6fc3628bcde2fb9297d5336008bcf678be https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index bdc3ba84719f..335d4d4d273e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -64,83 +64,83 @@ 3.8.0-2.20407.3 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 - 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.12 + 5.0.0-rc.1.20424.16 3.2.0 - 5.0.0-rc.1.20424.9 - 5.0.0-rc.1.20424.9 - 5.0.0-rc.1.20424.9 - 5.0.0-rc.1.20424.9 - 5.0.0-rc.1.20424.9 - 5.0.0-rc.1.20424.9 - 5.0.0-rc.1.20424.9 - 5.0.0-rc.1.20424.9 + 5.0.0-rc.1.20424.10 + 5.0.0-rc.1.20424.10 + 5.0.0-rc.1.20424.10 + 5.0.0-rc.1.20424.10 + 5.0.0-rc.1.20424.10 + 5.0.0-rc.1.20424.10 + 5.0.0-rc.1.20424.10 + 5.0.0-rc.1.20424.10 3.2.0 - 5.0.0-rc.1.20424.10 - 5.0.0-rc.1.20424.10 - 5.0.0-rc.1.20424.10 - 5.0.0-rc.1.20424.10 - 5.0.0-rc.1.20424.10 - 5.0.0-rc.1.20424.10 - 5.0.0-rc.1.20424.10 - 5.0.0-rc.1.20424.10 + 5.0.0-rc.1.20425.2 + 5.0.0-rc.1.20425.2 + 5.0.0-rc.1.20425.2 + 5.0.0-rc.1.20425.2 + 5.0.0-rc.1.20425.2 + 5.0.0-rc.1.20425.2 + 5.0.0-rc.1.20425.2 + 5.0.0-rc.1.20425.2 - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db - + https://github.com/dotnet/runtime - 6db9bb6fc3628bcde2fb9297d5336008bcf678be + f4e99f4afa445b519abcd7c5c87cbf54771614db https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index d2159e646435..95429244e70a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -64,83 +64,83 @@ 3.8.0-2.20407.3 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 - 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 - 5.0.0-rc.1.20424.16 + 5.0.0-rc.1.20425.1 3.2.0 - 5.0.0-rc.1.20425.2 - 5.0.0-rc.1.20425.2 - 5.0.0-rc.1.20425.2 - 5.0.0-rc.1.20425.2 - 5.0.0-rc.1.20425.2 - 5.0.0-rc.1.20425.2 - 5.0.0-rc.1.20425.2 - 5.0.0-rc.1.20425.2 + 5.0.0-rc.1.20425.3 + 5.0.0-rc.1.20425.3 + 5.0.0-rc.1.20425.3 + 5.0.0-rc.1.20425.3 + 5.0.0-rc.1.20425.3 + 5.0.0-rc.1.20425.3 + 5.0.0-rc.1.20425.3 + 5.0.0-rc.1.20425.3 .*?"; + + public ClientRenderingMultpleComponentsTest( + BrowserFixture browserFixture, + BasicTestAppServerSiteFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + } + + public DateTime LastLogTimeStamp { get; set; } = DateTime.MinValue; + + public override async Task InitializeAsync() + { + await base.InitializeAsync(); + + // Capture the last log timestamp so that we can filter logs when we + // check for duplicate connections. + var lastLog = Browser.Manage().Logs.GetLog(LogType.Browser).LastOrDefault(); + if (lastLog != null) + { + LastLogTimeStamp = lastLog.Timestamp; + } + } + + [Fact] + public void CanRenderMultipleRootComponents() + { + Navigate("/Client/multiple-components"); + + var greets = Browser.FindElements(By.CssSelector(".greet-wrapper .greet")).Select(e => e.Text).ToArray(); + + Assert.Equal(7, greets.Length); // 1 statically rendered + 5 prerendered + 1 server prerendered + Assert.DoesNotContain("Hello Red fish", greets); + Assert.Single(greets, "Hello John"); + Assert.Single(greets, "Hello Abraham"); + Assert.Equal(2, greets.Where(g => g == "Hello Blue fish").Count()); + Assert.Equal(3, greets.Where(g => string.Equals("Hello", g)).Count()); // 3 server prerendered without parameters + var content = Browser.FindElement(By.Id("test-container")).GetAttribute("innerHTML"); + var markers = ReadMarkers(content); + var componentSequence = markers.Select(m => m.Item1.PrerenderId != null).ToArray(); + Assert.Equal(13, componentSequence.Length); + + // Once the app starts, output changes + BeginInteractivity(); + + Browser.Exists(By.CssSelector("h3.interactive")); + var updatedGreets = Browser.FindElements(By.CssSelector(".greet-wrapper .greet")).Select(e => e.Text).ToArray(); + Assert.Equal(7, updatedGreets.Where(g => string.Equals("Hello Alfred", g)).Count()); + Assert.Equal(2, updatedGreets.Where(g => g == "Hello Red fish").Count()); + Assert.Equal(2, updatedGreets.Where(g => g == "Hello Blue fish").Count()); + Assert.Single(updatedGreets.Where(g => string.Equals("Hello Albert", g))); + Assert.Single(updatedGreets.Where(g => string.Equals("Hello Abraham", g))); + } + + private (WebAssemblyComponentMarker, WebAssemblyComponentMarker)[] ReadMarkers(string content) + { + content = content.Replace("\r\n", ""); + var matches = Regex.Matches(content, MarkerPattern); + var markers = matches.Select(s => JsonSerializer.Deserialize( + s.Groups[1].Value, + WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + + var prerenderMarkers = markers.Where(m => m.PrerenderId != null).GroupBy(p => p.PrerenderId).Select(g => (g.First(), g.Skip(1).First())).ToArray(); + var nonPrerenderMarkers = markers.Where(m => m.PrerenderId == null).Select(g => (g, (WebAssemblyComponentMarker)default)).ToArray(); + + return prerenderMarkers.Concat(nonPrerenderMarkers).ToArray(); + } + + private void BeginInteractivity() + { + Browser.FindElement(By.Id("load-boot-script")).Click(); + } + } +} diff --git a/src/Components/test/testassets/TestServer/MultipleComponents.cs b/src/Components/test/testassets/TestServer/MultipleComponents.cs index b48de346df70..3a3bf468a62a 100644 --- a/src/Components/test/testassets/TestServer/MultipleComponents.cs +++ b/src/Components/test/testassets/TestServer/MultipleComponents.cs @@ -32,6 +32,18 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } + app.Map("/Client/multiple-components", app => + { + app.UseBlazorFrameworkFiles(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); + endpoints.MapFallbackToPage("/Client/MultipleComponents"); + }); + }); + app.Map("/multiple-components", app => { app.UseStaticFiles(); diff --git a/src/Components/test/testassets/TestServer/Pages/Client/MultipleComponents.cshtml b/src/Components/test/testassets/TestServer/Pages/Client/MultipleComponents.cshtml new file mode 100644 index 000000000000..0f7078e0e603 --- /dev/null +++ b/src/Components/test/testassets/TestServer/Pages/Client/MultipleComponents.cshtml @@ -0,0 +1,29 @@ +@page "/multiple-components" +@using BasicTestApp.MultipleComponents; + +@{ + Layout = "./MultipleComponentsLayout.cshtml"; +} + + +@(await Html.RenderComponentAsync(RenderMode.WebAssemblyPrerendered)) +@(await Html.RenderComponentAsync(RenderMode.WebAssembly)) + + +
+

Some content before

+ +

Some content between

+ +

Some content after

+
+

Some content before

+ + +

Some content after

+
+
+
+ + +
diff --git a/src/Components/test/testassets/TestServer/Pages/Client/MultipleComponentsLayout.cshtml b/src/Components/test/testassets/TestServer/Pages/Client/MultipleComponentsLayout.cshtml new file mode 100644 index 000000000000..e46aae2983eb --- /dev/null +++ b/src/Components/test/testassets/TestServer/Pages/Client/MultipleComponentsLayout.cshtml @@ -0,0 +1,45 @@ +@using BasicTestApp.MultipleComponents; + + + + + Multiple component entry points + @* We need to make sure base is set to "/" so that the libraries load correctly *@ + + @* This page is used to validate the ability to render multiple root components in a blazor webassembly application. + *@ + + +
+ + + @RenderBody() + + +
+ + @* + So that E2E tests can make assertions about both the prerendered and + interactive states, we only load the .js file when told to. + *@ +
+ + + + + + + + + diff --git a/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs b/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs index 4bac5c8fc74c..0f7a565c25b3 100644 --- a/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs +++ b/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -66,6 +66,8 @@ public RenderMode RenderMode case RenderMode.Server: case RenderMode.ServerPrerendered: case RenderMode.Static: + case RenderMode.WebAssembly: + case RenderMode.WebAssemblyPrerendered: _renderMode = value; break; diff --git a/src/Mvc/Mvc.ViewFeatures/src/ClientComponentSerializer.cs b/src/Mvc/Mvc.ViewFeatures/src/ClientComponentSerializer.cs new file mode 100644 index 000000000000..5f8bf440620a --- /dev/null +++ b/src/Mvc/Mvc.ViewFeatures/src/ClientComponentSerializer.cs @@ -0,0 +1,75 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Microsoft.AspNetCore.Components; + +namespace Microsoft.AspNetCore.Mvc.ViewFeatures +{ + // See the details of the component serialization protocol in WebAssemblyComponentDeserializer.cs on the Components solution. + internal class WebAssemblyComponentSerializer + { + public WebAssemblyComponentMarker SerializeInvocation(Type type, ParameterView parameters, bool prerendered) + { + var assembly = type.Assembly.GetName().Name; + var typeFullName = type.FullName; + var (definitions, values) = ComponentParameter.FromParameterView(parameters); + + // We need to serialize and Base64 encode parameters separately since they can contain arbitrary data that might + // cause the HTML comment to be invalid (like if you serialize a string that contains two consecutive dashes "--"). + var serializedDefinitions = Convert.ToBase64String(JsonSerializer.SerializeToUtf8Bytes(definitions, WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + var serializedValues = Convert.ToBase64String(JsonSerializer.SerializeToUtf8Bytes(values, WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + + return prerendered ? WebAssemblyComponentMarker.Prerendered(assembly, typeFullName, serializedDefinitions, serializedValues) : + WebAssemblyComponentMarker.NonPrerendered(assembly, typeFullName, serializedDefinitions, serializedValues); + } + + internal IEnumerable GetPreamble(WebAssemblyComponentMarker record) + { + var serializedStartRecord = JsonSerializer.Serialize( + record, + WebAssemblyComponentSerializationSettings.JsonSerializationOptions); + + if (record.PrerenderId != null) + { + return PrerenderedStart(serializedStartRecord); + } + else + { + return NonPrerenderedSequence(serializedStartRecord); + } + + static IEnumerable PrerenderedStart(string startRecord) + { + yield return ""; + } + + static IEnumerable NonPrerenderedSequence(string record) + { + yield return ""; + } + } + + internal IEnumerable GetEpilogue(WebAssemblyComponentMarker record) + { + var serializedStartRecord = JsonSerializer.Serialize( + record.GetEndRecord(), + WebAssemblyComponentSerializationSettings.JsonSerializationOptions); + + return PrerenderEnd(serializedStartRecord); + + static IEnumerable PrerenderEnd(string endRecord) + { + yield return ""; + } + } + } +} diff --git a/src/Mvc/Mvc.ViewFeatures/src/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs b/src/Mvc/Mvc.ViewFeatures/src/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs index 84ffe50ce1c2..933145e614ed 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs @@ -177,6 +177,9 @@ internal static void AddViewServices(IServiceCollection services) // Component services for Blazor server-side interop services.TryAddSingleton(); + // Component services for Blazor webassembly interop + services.TryAddSingleton(); + // // View Components // diff --git a/src/Mvc/Mvc.ViewFeatures/src/Microsoft.AspNetCore.Mvc.ViewFeatures.csproj b/src/Mvc/Mvc.ViewFeatures/src/Microsoft.AspNetCore.Mvc.ViewFeatures.csproj index 56f7a3921815..0a93600bcf97 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/Microsoft.AspNetCore.Mvc.ViewFeatures.csproj +++ b/src/Mvc/Mvc.ViewFeatures/src/Microsoft.AspNetCore.Mvc.ViewFeatures.csproj @@ -1,4 +1,4 @@ - + @@ -31,7 +31,9 @@
+ + diff --git a/src/Mvc/Mvc.ViewFeatures/src/PublicAPI.Unshipped.txt b/src/Mvc/Mvc.ViewFeatures/src/PublicAPI.Unshipped.txt index 4b6567f9ced7..e371b29c8d18 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/PublicAPI.Unshipped.txt +++ b/src/Mvc/Mvc.ViewFeatures/src/PublicAPI.Unshipped.txt @@ -77,6 +77,8 @@ Microsoft.AspNetCore.Mvc.Rendering.RenderMode Microsoft.AspNetCore.Mvc.Rendering.RenderMode.Server = 2 -> Microsoft.AspNetCore.Mvc.Rendering.RenderMode Microsoft.AspNetCore.Mvc.Rendering.RenderMode.ServerPrerendered = 3 -> Microsoft.AspNetCore.Mvc.Rendering.RenderMode Microsoft.AspNetCore.Mvc.Rendering.RenderMode.Static = 1 -> Microsoft.AspNetCore.Mvc.Rendering.RenderMode +Microsoft.AspNetCore.Mvc.Rendering.RenderMode.WebAssembly = 4 -> Microsoft.AspNetCore.Mvc.Rendering.RenderMode +Microsoft.AspNetCore.Mvc.Rendering.RenderMode.WebAssemblyPrerendered = 5 -> Microsoft.AspNetCore.Mvc.Rendering.RenderMode Microsoft.AspNetCore.Mvc.Rendering.SelectList Microsoft.AspNetCore.Mvc.Rendering.SelectListGroup Microsoft.AspNetCore.Mvc.Rendering.SelectListGroup.Disabled.get -> bool diff --git a/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/ComponentRenderer.cs b/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/ComponentRenderer.cs index 44a618fb04a1..0ba79b592712 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/ComponentRenderer.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/ComponentRenderer.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -15,13 +15,16 @@ internal class ComponentRenderer : IComponentRenderer private static readonly object ComponentSequenceKey = new object(); private readonly StaticComponentRenderer _staticComponentRenderer; private readonly ServerComponentSerializer _serverComponentSerializer; + private readonly WebAssemblyComponentSerializer _WebAssemblyComponentSerializer; public ComponentRenderer( StaticComponentRenderer staticComponentRenderer, - ServerComponentSerializer serverComponentSerializer) + ServerComponentSerializer serverComponentSerializer, + WebAssemblyComponentSerializer WebAssemblyComponentSerializer) { _staticComponentRenderer = staticComponentRenderer; _serverComponentSerializer = serverComponentSerializer; + _WebAssemblyComponentSerializer = WebAssemblyComponentSerializer; } public async Task RenderComponentAsync( @@ -55,6 +58,8 @@ public async Task RenderComponentAsync( RenderMode.Server => NonPrerenderedServerComponent(context, GetOrCreateInvocationId(viewContext), componentType, parameterView), RenderMode.ServerPrerendered => await PrerenderedServerComponentAsync(context, GetOrCreateInvocationId(viewContext), componentType, parameterView), RenderMode.Static => await StaticComponentAsync(context, componentType, parameterView), + RenderMode.WebAssembly => NonPrerenderedWebAssemblyComponent(context, componentType, parameterView), + RenderMode.WebAssemblyPrerendered => await PrerenderedWebAssemblyComponentAsync(context, componentType, parameterView), _ => throw new ArgumentException(Resources.FormatUnsupportedRenderMode(renderMode), nameof(renderMode)), }; } @@ -99,12 +104,36 @@ private async Task PrerenderedServerComponentAsync(HttpContext con _serverComponentSerializer.GetEpilogue(currentInvocation)); } + private async Task PrerenderedWebAssemblyComponentAsync(HttpContext context, Type type, ParameterView parametersCollection) + { + var currentInvocation = _WebAssemblyComponentSerializer.SerializeInvocation( + type, + parametersCollection, + prerendered: true); + + var result = await _staticComponentRenderer.PrerenderComponentAsync( + parametersCollection, + context, + type); + + return new ComponentHtmlContent( + _WebAssemblyComponentSerializer.GetPreamble(currentInvocation), + result, + _WebAssemblyComponentSerializer.GetEpilogue(currentInvocation)); + } + private IHtmlContent NonPrerenderedServerComponent(HttpContext context, ServerComponentInvocationSequence invocationId, Type type, ParameterView parametersCollection) { - var serviceProvider = context.RequestServices; var currentInvocation = _serverComponentSerializer.SerializeInvocation(invocationId, type, parametersCollection, prerendered: false); return new ComponentHtmlContent(_serverComponentSerializer.GetPreamble(currentInvocation)); } + + private IHtmlContent NonPrerenderedWebAssemblyComponent(HttpContext context, Type type, ParameterView parametersCollection) + { + var currentInvocation = _WebAssemblyComponentSerializer.SerializeInvocation(type, parametersCollection, prerendered: false); + + return new ComponentHtmlContent(_WebAssemblyComponentSerializer.GetPreamble(currentInvocation)); + } } } diff --git a/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/StaticComponentRenderer.cs b/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/StaticComponentRenderer.cs index 411e6014a8f4..7a8a8dd62ded 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/StaticComponentRenderer.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/StaticComponentRenderer.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -32,7 +32,7 @@ public async Task> PrerenderComponentAsync( Type componentType) { InitializeStandardComponentServices(httpContext); - var loggerFactory = (ILoggerFactory)httpContext.RequestServices.GetService(typeof (ILoggerFactory)); + var loggerFactory = (ILoggerFactory)httpContext.RequestServices.GetService(typeof(ILoggerFactory)); using (var htmlRenderer = new HtmlRenderer(httpContext.RequestServices, loggerFactory, _encoder.Encode)) { ComponentRenderedText result = default; @@ -71,15 +71,15 @@ private void InitializeStandardComponentServices(HttpContext httpContext) { _initialized = true; + var navigationManager = (IHostEnvironmentNavigationManager)httpContext.RequestServices.GetRequiredService(); + navigationManager?.Initialize(GetContextBaseUri(httpContext.Request), GetFullUri(httpContext.Request)); + var authenticationStateProvider = httpContext.RequestServices.GetService() as IHostEnvironmentAuthenticationStateProvider; if (authenticationStateProvider != null) { var authenticationState = new AuthenticationState(httpContext.User); authenticationStateProvider.SetAuthenticationState(Task.FromResult(authenticationState)); } - - var navigationManager = (IHostEnvironmentNavigationManager)httpContext.RequestServices.GetRequiredService(); - navigationManager?.Initialize(GetContextBaseUri(httpContext.Request), GetFullUri(httpContext.Request)); } } diff --git a/src/Mvc/Mvc.ViewFeatures/src/RenderMode.cs b/src/Mvc/Mvc.ViewFeatures/src/RenderMode.cs index f6816e68ff4f..d0422753cb3e 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/RenderMode.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/RenderMode.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. namespace Microsoft.AspNetCore.Mvc.Rendering @@ -30,5 +30,16 @@ public enum RenderMode /// ServerPrerendered = 3, + /// + /// Renders a marker for a Blazor webassembly application. This doesn't include any output from the component. + /// When the user-agent starts, it uses this marker to bootstrap a blazor client-side application. + /// + WebAssembly = 4, + + /// + /// Renders the component into static HTML and includes a marker for a Blazor webassembly application. + /// When the user-agent starts, it uses this marker to bootstrap a blazor client-side application. + /// + WebAssemblyPrerendered = 5, } } diff --git a/src/Mvc/Mvc.ViewFeatures/test/RazorComponents/ComponentRendererTest.cs b/src/Mvc/Mvc.ViewFeatures/test/RazorComponents/ComponentRendererTest.cs index f9e403ca2f6e..e20a4203b931 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/RazorComponents/ComponentRendererTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/RazorComponents/ComponentRendererTest.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.RegularExpressions; @@ -26,13 +27,239 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures { public class ComponentRendererTest { - private const string PrerenderedServerComponentPattern = "^(?.+?)$"; - private const string ServerComponentPattern = "^$"; + private const string PrerenderedComponentPattern = "^(?.+?)$"; + private const string ComponentPattern = "^$"; private static readonly IDataProtectionProvider _dataprotectorProvider = new EphemeralDataProtectionProvider(); private readonly ComponentRenderer renderer = GetComponentRenderer(); + [Fact] + public async Task CanRender_ParameterlessComponent_ClientMode() + { + // Arrange + var viewContext = GetViewContext(); + var writer = new StringWriter(); + + // Act + var result = await renderer.RenderComponentAsync(viewContext, typeof(TestComponent), RenderMode.WebAssembly, null); + result.WriteTo(writer, HtmlEncoder.Default); + var content = writer.ToString(); + var match = Regex.Match(content, ComponentPattern); + + // Assert + Assert.True(match.Success); + var marker = JsonSerializer.Deserialize(match.Groups[1].Value, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.Null(marker.PrerenderId); + Assert.Equal("webassembly", marker.Type); + Assert.Equal(typeof(TestComponent).Assembly.GetName().Name, marker.Assembly); + Assert.Equal(typeof(TestComponent).FullName, marker.TypeName); + } + + [Fact] + public async Task CanPrerender_ParameterlessComponent_ClientMode() + { + // Arrange + var viewContext = GetViewContext(); + var writer = new StringWriter(); + + // Act + var result = await renderer.RenderComponentAsync(viewContext, typeof(TestComponent), RenderMode.WebAssemblyPrerendered, null); + result.WriteTo(writer, HtmlEncoder.Default); + var content = writer.ToString(); + var match = Regex.Match(content, PrerenderedComponentPattern, RegexOptions.Multiline); + + // Assert + Assert.True(match.Success); + var preamble = match.Groups["preamble"].Value; + var preambleMarker = JsonSerializer.Deserialize(preamble, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.NotNull(preambleMarker.PrerenderId); + Assert.Equal("webassembly", preambleMarker.Type); + Assert.Equal(typeof(TestComponent).Assembly.GetName().Name, preambleMarker.Assembly); + Assert.Equal(typeof(TestComponent).FullName, preambleMarker.TypeName); + + var prerenderedContent = match.Groups["content"].Value; + Assert.Equal("

Hello world!

", prerenderedContent); + + var epilogue = match.Groups["epilogue"].Value; + var epilogueMarker = JsonSerializer.Deserialize(epilogue, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.Equal(preambleMarker.PrerenderId, epilogueMarker.PrerenderId); + Assert.Null(epilogueMarker.Assembly); + Assert.Null(epilogueMarker.TypeName); + Assert.Null(epilogueMarker.Type); + Assert.Null(epilogueMarker.ParameterDefinitions); + Assert.Null(epilogueMarker.ParameterValues); + } + + [Fact] + public async Task CanRender_ComponentWithParameters_ClientMode() + { + // Arrange + var viewContext = GetViewContext(); + var writer = new StringWriter(); + + // Act + var result = await renderer.RenderComponentAsync(viewContext, typeof(GreetingComponent), + RenderMode.WebAssembly, + new + { + Name = "Daniel" + }); + result.WriteTo(writer, HtmlEncoder.Default); + var content = writer.ToString(); + var match = Regex.Match(content, ComponentPattern); + + // Assert + Assert.True(match.Success); + var marker = JsonSerializer.Deserialize(match.Groups[1].Value, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.Null(marker.PrerenderId); + Assert.Equal("webassembly", marker.Type); + Assert.Equal(typeof(GreetingComponent).Assembly.GetName().Name, marker.Assembly); + Assert.Equal(typeof(GreetingComponent).FullName, marker.TypeName); + + var parameterDefinition = Assert.Single( + JsonSerializer.Deserialize(Convert.FromBase64String(marker.ParameterDefinitions), WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + Assert.Equal("Name", parameterDefinition.Name); + Assert.Equal("System.String", parameterDefinition.TypeName); + Assert.Equal("System.Private.CoreLib", parameterDefinition.Assembly); + + var value = Assert.Single(JsonSerializer.Deserialize(Convert.FromBase64String(marker.ParameterValues), WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + var rawValue = Assert.IsType(value); + Assert.Equal("Daniel", rawValue.GetString()); + } + + [Fact] + public async Task CanRender_ComponentWithNullParameters_ClientMode() + { + // Arrange + var viewContext = GetViewContext(); + var writer = new StringWriter(); + + // Act + var result = await renderer.RenderComponentAsync(viewContext, typeof(GreetingComponent), + RenderMode.WebAssembly, + new + { + Name = (string)null + }); + result.WriteTo(writer, HtmlEncoder.Default); + var content = writer.ToString(); + var match = Regex.Match(content, ComponentPattern); + + // Assert + Assert.True(match.Success); + var marker = JsonSerializer.Deserialize(match.Groups[1].Value, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.Null(marker.PrerenderId); + Assert.Equal("webassembly", marker.Type); + Assert.Equal(typeof(GreetingComponent).Assembly.GetName().Name, marker.Assembly); + Assert.Equal(typeof(GreetingComponent).FullName, marker.TypeName); + + var parameterDefinition = Assert.Single(JsonSerializer.Deserialize(Convert.FromBase64String(marker.ParameterDefinitions), WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + Assert.Equal("Name", parameterDefinition.Name); + Assert.Null(parameterDefinition.TypeName); + Assert.Null(parameterDefinition.Assembly); + + var value = Assert.Single(JsonSerializer.Deserialize(Convert.FromBase64String(marker.ParameterValues), WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + Assert.Null(value); + } + + [Fact] + public async Task CanPrerender_ComponentWithParameters_ClientMode() + { + // Arrange + var viewContext = GetViewContext(); + var writer = new StringWriter(); + + // Act + var result = await renderer.RenderComponentAsync(viewContext, typeof(GreetingComponent), + RenderMode.WebAssemblyPrerendered, + new + { + Name = "Daniel" + }); + result.WriteTo(writer, HtmlEncoder.Default); + var content = writer.ToString(); + var match = Regex.Match(content, PrerenderedComponentPattern, RegexOptions.Multiline); + + // Assert + Assert.True(match.Success); + var preamble = match.Groups["preamble"].Value; + var preambleMarker = JsonSerializer.Deserialize(preamble, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.NotNull(preambleMarker.PrerenderId); + Assert.Equal("webassembly", preambleMarker.Type); + Assert.Equal(typeof(GreetingComponent).Assembly.GetName().Name, preambleMarker.Assembly); + Assert.Equal(typeof(GreetingComponent).FullName, preambleMarker.TypeName); + + var parameterDefinition = Assert.Single(JsonSerializer.Deserialize(Convert.FromBase64String(preambleMarker.ParameterDefinitions), WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + Assert.Equal("Name", parameterDefinition.Name); + Assert.Equal("System.String", parameterDefinition.TypeName); + Assert.Equal("System.Private.CoreLib", parameterDefinition.Assembly); + + var value = Assert.Single(JsonSerializer.Deserialize(Convert.FromBase64String(preambleMarker.ParameterValues), WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + var rawValue = Assert.IsType(value); + Assert.Equal("Daniel", rawValue.GetString()); + + var prerenderedContent = match.Groups["content"].Value; + Assert.Equal("

Hello Daniel!

", prerenderedContent); + + var epilogue = match.Groups["epilogue"].Value; + var epilogueMarker = JsonSerializer.Deserialize(epilogue, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.Equal(preambleMarker.PrerenderId, epilogueMarker.PrerenderId); + Assert.Null(epilogueMarker.Assembly); + Assert.Null(epilogueMarker.TypeName); + Assert.Null(epilogueMarker.Type); + Assert.Null(epilogueMarker.ParameterDefinitions); + Assert.Null(epilogueMarker.ParameterValues); + } + + [Fact] + public async Task CanPrerender_ComponentWithNullParameters_ClientMode() + { + // Arrange + var viewContext = GetViewContext(); + var writer = new StringWriter(); + + // Act + var result = await renderer.RenderComponentAsync(viewContext, typeof(GreetingComponent), + RenderMode.WebAssemblyPrerendered, + new + { + Name = (string)null + }); + result.WriteTo(writer, HtmlEncoder.Default); + var content = writer.ToString(); + var match = Regex.Match(content, PrerenderedComponentPattern, RegexOptions.Multiline); + + // Assert + Assert.True(match.Success); + var preamble = match.Groups["preamble"].Value; + var preambleMarker = JsonSerializer.Deserialize(preamble, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.NotNull(preambleMarker.PrerenderId); + Assert.Equal("webassembly", preambleMarker.Type); + Assert.Equal(typeof(GreetingComponent).Assembly.GetName().Name, preambleMarker.Assembly); + Assert.Equal(typeof(GreetingComponent).FullName, preambleMarker.TypeName); + + var parameterDefinition = Assert.Single(JsonSerializer.Deserialize(Convert.FromBase64String(preambleMarker.ParameterDefinitions), WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + Assert.Equal("Name", parameterDefinition.Name); + Assert.Null(parameterDefinition.TypeName); + Assert.Null(parameterDefinition.Assembly); + + var value = Assert.Single(JsonSerializer.Deserialize(Convert.FromBase64String(preambleMarker.ParameterValues), WebAssemblyComponentSerializationSettings.JsonSerializationOptions)); + Assert.Null(value); + + var prerenderedContent = match.Groups["content"].Value; + Assert.Equal("

Hello (null)!

", prerenderedContent); + + var epilogue = match.Groups["epilogue"].Value; + var epilogueMarker = JsonSerializer.Deserialize(epilogue, ServerComponentSerializationSettings.JsonSerializationOptions); + Assert.Equal(preambleMarker.PrerenderId, epilogueMarker.PrerenderId); + Assert.Null(epilogueMarker.Assembly); + Assert.Null(epilogueMarker.TypeName); + Assert.Null(epilogueMarker.Type); + Assert.Null(epilogueMarker.ParameterDefinitions); + Assert.Null(epilogueMarker.ParameterValues); + } + [Fact] public async Task CanRender_ParameterlessComponent() { @@ -60,7 +287,7 @@ public async Task CanRender_ParameterlessComponent_ServerMode() // Act var result = await renderer.RenderComponentAsync(viewContext, typeof(TestComponent), RenderMode.Server, null); var content = HtmlContentUtilities.HtmlContentToString(result); - var match = Regex.Match(content, ServerComponentPattern); + var match = Regex.Match(content, ComponentPattern); // Assert Assert.True(match.Success); @@ -89,7 +316,7 @@ public async Task CanPrerender_ParameterlessComponent_ServerMode() // Act var result = await renderer.RenderComponentAsync(viewContext, typeof(TestComponent), RenderMode.ServerPrerendered, null); var content = HtmlContentUtilities.HtmlContentToString(result); - var match = Regex.Match(content, PrerenderedServerComponentPattern, RegexOptions.Multiline); + var match = Regex.Match(content, PrerenderedComponentPattern, RegexOptions.Multiline); // Assert Assert.True(match.Success); @@ -130,11 +357,11 @@ public async Task CanRenderMultipleServerComponents() // Act var firstResult = await renderer.RenderComponentAsync(viewContext, typeof(TestComponent), RenderMode.ServerPrerendered, null); var firstComponent = HtmlContentUtilities.HtmlContentToString(firstResult); - var firstMatch = Regex.Match(firstComponent, PrerenderedServerComponentPattern, RegexOptions.Multiline); + var firstMatch = Regex.Match(firstComponent, PrerenderedComponentPattern, RegexOptions.Multiline); var secondResult = await renderer.RenderComponentAsync(viewContext, typeof(TestComponent), RenderMode.Server, null); var secondComponent = HtmlContentUtilities.HtmlContentToString(secondResult); - var secondMatch = Regex.Match(secondComponent, ServerComponentPattern); + var secondMatch = Regex.Match(secondComponent, ComponentPattern); // Assert Assert.True(firstMatch.Success); @@ -186,7 +413,7 @@ public async Task CanRender_ComponentWithParameters_ServerMode() // Act var result = await renderer.RenderComponentAsync(viewContext, typeof(GreetingComponent), RenderMode.Server, new { Name = "Daniel" }); var content = HtmlContentUtilities.HtmlContentToString(result); - var match = Regex.Match(content, ServerComponentPattern); + var match = Regex.Match(content, ComponentPattern); // Assert Assert.True(match.Success); @@ -225,7 +452,7 @@ public async Task CanRender_ComponentWithNullParameters_ServerMode() var result = await renderer.RenderComponentAsync(viewContext, typeof(GreetingComponent), RenderMode.Server, new { Name = (string)null }); var content = HtmlContentUtilities.HtmlContentToString(result); - var match = Regex.Match(content, ServerComponentPattern); + var match = Regex.Match(content, ComponentPattern); // Assert Assert.True(match.Success); @@ -264,7 +491,7 @@ public async Task CanPrerender_ComponentWithParameters_ServerPrerenderedMode() // Act var result = await renderer.RenderComponentAsync(viewContext, typeof(GreetingComponent), RenderMode.ServerPrerendered, new { Name = "Daniel" }); var content = HtmlContentUtilities.HtmlContentToString(result); - var match = Regex.Match(content, PrerenderedServerComponentPattern, RegexOptions.Multiline); + var match = Regex.Match(content, PrerenderedComponentPattern, RegexOptions.Multiline); // Assert Assert.True(match.Success); @@ -315,7 +542,7 @@ public async Task CanPrerender_ComponentWithNullParameters_ServerPrerenderedMode // Act var result = await renderer.RenderComponentAsync(viewContext, typeof(GreetingComponent), RenderMode.ServerPrerendered, new { Name = (string)null }); var content = HtmlContentUtilities.HtmlContentToString(result); - var match = Regex.Match(content, PrerenderedServerComponentPattern, RegexOptions.Multiline); + var match = Regex.Match(content, PrerenderedComponentPattern, RegexOptions.Multiline); // Assert Assert.True(match.Success); @@ -554,7 +781,7 @@ public async Task CanRender_AsyncComponent() "; // Act - var result = await renderer.RenderComponentAsync(viewContext,typeof(AsyncComponent), RenderMode.Static, null); + var result = await renderer.RenderComponentAsync(viewContext, typeof(AsyncComponent), RenderMode.Static, null); var content = HtmlContentUtilities.HtmlContentToString(result); // Assert @@ -564,7 +791,8 @@ public async Task CanRender_AsyncComponent() private static ComponentRenderer GetComponentRenderer() => new ComponentRenderer( new StaticComponentRenderer(HtmlEncoder.Default), - new ServerComponentSerializer(_dataprotectorProvider)); + new ServerComponentSerializer(_dataprotectorProvider), + new WebAssemblyComponentSerializer()); private static ViewContext GetViewContext(HttpContext context = null, Action configureServices = null) { diff --git a/src/Shared/Components/WebAssemblyComponentMarker.cs b/src/Shared/Components/WebAssemblyComponentMarker.cs new file mode 100644 index 000000000000..bd8fab295aea --- /dev/null +++ b/src/Shared/Components/WebAssemblyComponentMarker.cs @@ -0,0 +1,43 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.AspNetCore.Components +{ + internal struct WebAssemblyComponentMarker + { + public const string ClientMarkerType = "webassembly"; + + public WebAssemblyComponentMarker(string type, string assembly, string typeName, string parameterDefinitions, string parameterValues, string prereenderId) => + (Type, Assembly, TypeName, ParameterDefinitions, ParameterValues, PrerenderId) = (type, assembly, typeName, parameterDefinitions, parameterValues, prereenderId); + + public string Type { get; set; } + + public string Assembly { get; set; } + + public string TypeName { get; set; } + + public string ParameterDefinitions { get; set; } + + public string ParameterValues { get; set; } + + public string PrerenderId { get; set; } + + internal static WebAssemblyComponentMarker NonPrerendered(string assembly, string typeName, string parameterDefinitions, string parameterValues) => + new WebAssemblyComponentMarker(ClientMarkerType, assembly, typeName, parameterDefinitions, parameterValues, null); + + internal static WebAssemblyComponentMarker Prerendered(string assembly, string typeName, string parameterDefinitions, string parameterValues) => + new WebAssemblyComponentMarker(ClientMarkerType, assembly, typeName, parameterDefinitions, parameterValues, Guid.NewGuid().ToString("N")); + + public WebAssemblyComponentMarker GetEndRecord() + { + if (PrerenderId == null) + { + throw new InvalidOperationException("Can't get an end record for non-prerendered components."); + } + + return new WebAssemblyComponentMarker(null, null, null, null, null, PrerenderId); + } + } +} diff --git a/src/Shared/Components/WebAssemblyComponentSerializationSettings.cs b/src/Shared/Components/WebAssemblyComponentSerializationSettings.cs new file mode 100644 index 000000000000..741ab989d594 --- /dev/null +++ b/src/Shared/Components/WebAssemblyComponentSerializationSettings.cs @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Text.Json; + +namespace Microsoft.AspNetCore.Components +{ + internal static class WebAssemblyComponentSerializationSettings + { + public static readonly JsonSerializerOptions JsonSerializationOptions = + new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true, + IgnoreNullValues = true + }; + } +} diff --git a/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/.NETCoreApp,Version=v5.0.AssemblyAttributes.cs b/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/.NETCoreApp,Version=v5.0.AssemblyAttributes.cs new file mode 100644 index 000000000000..2f7e5ec5afa1 --- /dev/null +++ b/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/.NETCoreApp,Version=v5.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v5.0", FrameworkDisplayName = "")] diff --git a/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/KitchenSink.AssemblyInfo.cs b/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/KitchenSink.AssemblyInfo.cs new file mode 100644 index 000000000000..1172632a8716 --- /dev/null +++ b/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/KitchenSink.AssemblyInfo.cs @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyMetadataAttribute("SourceCommitUrl", "https://github.com/dotnet/aspnetcore/tree/")] +[assembly: System.Reflection.AssemblyMetadataAttribute("Serviceable", "True")] +[assembly: System.Reflection.AssemblyCompanyAttribute("Microsoft Corporation")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyCopyrightAttribute("© Microsoft Corporation. All rights reserved.")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("42.42.42.42424")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("5.0.0-dev")] +[assembly: System.Reflection.AssemblyProductAttribute("Microsoft ASP.NET Core")] +[assembly: System.Reflection.AssemblyTitleAttribute("KitchenSink")] +[assembly: System.Reflection.AssemblyVersionAttribute("5.0.0.0")] +[assembly: System.Reflection.AssemblyMetadataAttribute("RepositoryUrl", "https://github.com/dotnet/aspnetcore")] +[assembly: System.Resources.NeutralResourcesLanguageAttribute("en-US")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/KitchenSink.AssemblyInfoInputs.cache b/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/KitchenSink.AssemblyInfoInputs.cache new file mode 100644 index 000000000000..9042200dfcf3 --- /dev/null +++ b/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/.net/objDebug/net5.0/KitchenSink.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +5426b0432f23f134c800ff0d43b24a23681aac3d From 70ea49fd8a020e8652d90a8313bd17e6915f160c Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2020 17:00:07 +0000 Subject: [PATCH 16/26] Update dependencies from https://github.com/dotnet/efcore build 20200825.4 (#25243) [release/5.0] Update dependencies from dotnet/efcore - Updates: - Microsoft.EntityFrameworkCore.Tools: from 5.0.0-rc.1.20425.3 to 5.0.0-rc.1.20425.4 - Microsoft.EntityFrameworkCore.SqlServer: from 5.0.0-rc.1.20425.3 to 5.0.0-rc.1.20425.4 - dotnet-ef: from 5.0.0-rc.1.20425.3 to 5.0.0-rc.1.20425.4 - Microsoft.EntityFrameworkCore: from 5.0.0-rc.1.20425.3 to 5.0.0-rc.1.20425.4 - Microsoft.EntityFrameworkCore.Design: from 5.0.0-rc.1.20425.3 to 5.0.0-rc.1.20425.4 - Microsoft.EntityFrameworkCore.Relational: from 5.0.0-rc.1.20425.3 to 5.0.0-rc.1.20425.4 - Microsoft.EntityFrameworkCore.Sqlite: from 5.0.0-rc.1.20425.3 to 5.0.0-rc.1.20425.4 - Microsoft.EntityFrameworkCore.InMemory: from 5.0.0-rc.1.20425.3 to 5.0.0-rc.1.20425.4 --- eng/Version.Details.xml | 32 ++++++++++++++++---------------- eng/Versions.props | 16 ++++++++-------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ab3ec5f74e98..c89e801957f7 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,37 +13,37 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - fa4bb966c1fbc30b6334e658f20bba46cb0555c8 + 9638c0cda4bfb2eb8b70a047baefc982ffa7dade - + https://github.com/dotnet/efcore - fa4bb966c1fbc30b6334e658f20bba46cb0555c8 + 9638c0cda4bfb2eb8b70a047baefc982ffa7dade - + https://github.com/dotnet/efcore - fa4bb966c1fbc30b6334e658f20bba46cb0555c8 + 9638c0cda4bfb2eb8b70a047baefc982ffa7dade - + https://github.com/dotnet/efcore - fa4bb966c1fbc30b6334e658f20bba46cb0555c8 + 9638c0cda4bfb2eb8b70a047baefc982ffa7dade - + https://github.com/dotnet/efcore - fa4bb966c1fbc30b6334e658f20bba46cb0555c8 + 9638c0cda4bfb2eb8b70a047baefc982ffa7dade - + https://github.com/dotnet/efcore - fa4bb966c1fbc30b6334e658f20bba46cb0555c8 + 9638c0cda4bfb2eb8b70a047baefc982ffa7dade - + https://github.com/dotnet/efcore - fa4bb966c1fbc30b6334e658f20bba46cb0555c8 + 9638c0cda4bfb2eb8b70a047baefc982ffa7dade - + https://github.com/dotnet/efcore - fa4bb966c1fbc30b6334e658f20bba46cb0555c8 + 9638c0cda4bfb2eb8b70a047baefc982ffa7dade https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 95429244e70a..965ed5bdd1bb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -133,14 +133,14 @@ 3.2.0 - 5.0.0-rc.1.20425.3 - 5.0.0-rc.1.20425.3 - 5.0.0-rc.1.20425.3 - 5.0.0-rc.1.20425.3 - 5.0.0-rc.1.20425.3 - 5.0.0-rc.1.20425.3 - 5.0.0-rc.1.20425.3 - 5.0.0-rc.1.20425.3 + 5.0.0-rc.1.20425.4 + 5.0.0-rc.1.20425.4 + 5.0.0-rc.1.20425.4 + 5.0.0-rc.1.20425.4 + 5.0.0-rc.1.20425.4 + 5.0.0-rc.1.20425.4 + 5.0.0-rc.1.20425.4 + 5.0.0-rc.1.20425.4 false + + + true + true - - - - - + + + + - @@ -36,19 +45,5 @@
- - - <_RuntimeFramework Include="@(RuntimeFramework)" /> - - - - - - - - - - - diff --git a/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj b/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj index 66aea279ee62..346ddc48f16b 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj @@ -12,13 +12,18 @@ + + - + + + + - diff --git a/src/Components/test/testassets/TestServer/Components.TestServer.csproj b/src/Components/test/testassets/TestServer/Components.TestServer.csproj index 651b301bece8..59b8fe56856b 100644 --- a/src/Components/test/testassets/TestServer/Components.TestServer.csproj +++ b/src/Components/test/testassets/TestServer/Components.TestServer.csproj @@ -22,10 +22,13 @@ - + + + + <_Parameter1>Microsoft.AspNetCore.Testing.BasicTestApp.ContentRoot diff --git a/src/Tools/dotnet-watch/src/DotnetToolSettings.xml b/src/Tools/dotnet-watch/src/DotnetToolSettings.xml new file mode 100644 index 000000000000..f077af6da491 --- /dev/null +++ b/src/Tools/dotnet-watch/src/DotnetToolSettings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/Tools/dotnet-watch/src/dotnet-watch.csproj b/src/Tools/dotnet-watch/src/dotnet-watch.csproj index cbe5cf13c95e..29750598258e 100644 --- a/src/Tools/dotnet-watch/src/dotnet-watch.csproj +++ b/src/Tools/dotnet-watch/src/dotnet-watch.csproj @@ -10,6 +10,13 @@ false false + + + true + true @@ -20,8 +27,13 @@ - - + + + - - - <_RuntimeFramework Include="@(RuntimeFramework)" /> - - - - - - - - - - - - diff --git a/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj b/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj index d171daa39d84..b9c9d9fe3c2e 100644 --- a/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj +++ b/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj @@ -5,6 +5,13 @@ Microsoft.DotNet.Watcher.Tools.Tests $(DefaultItemExcludes);TestProjects\**\* DotNetWatcherToolsTests + + + true + true @@ -14,6 +21,7 @@ + From c2f03318052aa81ce67c6abb120aae892ae519e7 Mon Sep 17 00:00:00 2001 From: Doug Bunting <6431421+dougbu@users.noreply.github.com> Date: Tue, 25 Aug 2020 10:47:37 -0700 Subject: [PATCH 18/26] Include project file in F# Worker Service template (#25180) - add test of this project template --- .../Microsoft.DotNet.Web.ProjectTemplates.csproj | 1 + src/ProjectTemplates/test/WorkerTemplateTest.cs | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj b/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj index 9aa8755e9f05..e2021461e61c 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj +++ b/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj @@ -59,6 +59,7 @@ + diff --git a/src/ProjectTemplates/test/WorkerTemplateTest.cs b/src/ProjectTemplates/test/WorkerTemplateTest.cs index d7e471458510..1656ebb0896b 100644 --- a/src/ProjectTemplates/test/WorkerTemplateTest.cs +++ b/src/ProjectTemplates/test/WorkerTemplateTest.cs @@ -21,13 +21,17 @@ public WorkerTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelpe public ProjectFactoryFixture ProjectFactory { get; } public ITestOutputHelper Output { get; } - [ConditionalFact] + [ConditionalTheory] [OSSkipCondition(OperatingSystems.Linux, SkipReason = "https://github.com/dotnet/sdk/issues/12831")] - public async Task WorkerTemplateAsync() + [InlineData("C#")] + [InlineData("F#")] + public async Task WorkerTemplateAsync(string language) { - Project = await ProjectFactory.GetOrCreateProject("worker", Output); + Project = await ProjectFactory.GetOrCreateProject( + $"worker-{ language.ToLowerInvariant()[0] }sharp", + Output); - var createResult = await Project.RunDotNetNewAsync("worker"); + var createResult = await Project.RunDotNetNewAsync("worker", language: language); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); var publishResult = await Project.RunDotNetPublishAsync(); From 098be5f5ee2039ff7a184a4098802537390f2b35 Mon Sep 17 00:00:00 2001 From: John Luo Date: Tue, 25 Aug 2020 13:21:46 -0700 Subject: [PATCH 19/26] Use LDAP support from DirectoryServices.Protocols for RBAC claim resolution on Linux for Negotiate (#25075) --- eng/Dependencies.props | 1 + eng/Version.Details.xml | 4 + eng/Versions.props | 1 + .../samples/NegotiateAuthSample/Startup.cs | 18 ++++ .../Negotiate/src/Events/LdapContext.cs | 35 +++++++ .../Negotiate/src/Events/NegotiateEvents.cs | 11 +++ .../Negotiate/src/Internal/LdapAdapter.cs | 97 +++++++++++++++++++ ...NegotiateOptionsValidationStartupFilter.cs | 31 ++++++ .../Negotiate/src/LdapSettings.cs | 75 ++++++++++++++ ...AspNetCore.Authentication.Negotiate.csproj | 2 + .../Negotiate/src/NegotiateExtensions.cs | 3 + .../Negotiate/src/NegotiateHandler.cs | 34 ++++++- .../Negotiate/src/NegotiateOptions.cs | 38 ++++++++ .../src/PostConfigureNegotiateOptions.cs | 32 ++++++ .../test/Negotiate.Test/EventTests.cs | 23 ++++- .../LdapSettingsValidationTests.cs | 34 +++++++ .../Negotiate.Test/ServerDeferralTests.cs | 3 +- 17 files changed, 435 insertions(+), 7 deletions(-) create mode 100644 src/Security/Authentication/Negotiate/src/Events/LdapContext.cs create mode 100644 src/Security/Authentication/Negotiate/src/Internal/LdapAdapter.cs create mode 100644 src/Security/Authentication/Negotiate/src/Internal/NegotiateOptionsValidationStartupFilter.cs create mode 100644 src/Security/Authentication/Negotiate/src/LdapSettings.cs create mode 100644 src/Security/Authentication/Negotiate/test/Negotiate.Test/LdapSettingsValidationTests.cs diff --git a/eng/Dependencies.props b/eng/Dependencies.props index 8da95c63148c..68e1f6149cd7 100644 --- a/eng/Dependencies.props +++ b/eng/Dependencies.props @@ -64,6 +64,7 @@ and are generated based on the last package release. + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c89e801957f7..db9cc55f62af 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -205,6 +205,10 @@ https://github.com/dotnet/runtime f4e99f4afa445b519abcd7c5c87cbf54771614db + + https://github.com/dotnet/runtime + f4e99f4afa445b519abcd7c5c87cbf54771614db + https://github.com/dotnet/runtime f4e99f4afa445b519abcd7c5c87cbf54771614db diff --git a/eng/Versions.props b/eng/Versions.props index 965ed5bdd1bb..9c2fd0000ebc 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -108,6 +108,7 @@ 5.0.0-rc.1.20425.1 5.0.0-rc.1.20425.1 5.0.0-rc.1.20425.1 + 5.0.0-rc.1.20425.1 5.0.0-rc.1.20425.1 5.0.0-rc.1.20425.1 5.0.0-rc.1.20425.1 diff --git a/src/Security/Authentication/Negotiate/samples/NegotiateAuthSample/Startup.cs b/src/Security/Authentication/Negotiate/samples/NegotiateAuthSample/Startup.cs index 2e62846f8f5d..c2b0b0ba7f81 100644 --- a/src/Security/Authentication/Negotiate/samples/NegotiateAuthSample/Startup.cs +++ b/src/Security/Authentication/Negotiate/samples/NegotiateAuthSample/Startup.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication.Negotiate; using Microsoft.AspNetCore.Builder; @@ -22,6 +23,23 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(NegotiateDefaults.AuthenticationScheme) .AddNegotiate(options => { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + /* + options.EnableLdap("DOMAIN.net"); + + options.EnableLdap(settings => + { + // Mandatory settings + settings.Domain = "DOMAIN.com"; + // Optional settings + settings.MachineAccountName = "machineName"; + settings.MachineAccountPassword = "PassW0rd"; + settings.IgnoreNestedGroups = true; + }); + */ + } + options.Events = new NegotiateEvents() { OnAuthenticationFailed = context => diff --git a/src/Security/Authentication/Negotiate/src/Events/LdapContext.cs b/src/Security/Authentication/Negotiate/src/Events/LdapContext.cs new file mode 100644 index 000000000000..9e6d7a40ac82 --- /dev/null +++ b/src/Security/Authentication/Negotiate/src/Events/LdapContext.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication.Negotiate +{ + /// + /// State for the RetrieveLdapClaims event. + /// + public class LdapContext : ResultContext + { + /// + /// Creates a new . + /// + /// + /// + /// + /// + public LdapContext( + HttpContext context, + AuthenticationScheme scheme, + NegotiateOptions options, + LdapSettings settings) + : base(context, scheme, options) + { + LdapSettings = settings; + } + + /// + /// The LDAP settings to use for the RetrieveLdapClaims event. + /// + public LdapSettings LdapSettings { get; } + } +} diff --git a/src/Security/Authentication/Negotiate/src/Events/NegotiateEvents.cs b/src/Security/Authentication/Negotiate/src/Events/NegotiateEvents.cs index 0d57be28ebdc..88dfdf2b747b 100644 --- a/src/Security/Authentication/Negotiate/src/Events/NegotiateEvents.cs +++ b/src/Security/Authentication/Negotiate/src/Events/NegotiateEvents.cs @@ -16,6 +16,12 @@ public class NegotiateEvents /// public Func OnAuthenticationFailed { get; set; } = context => Task.CompletedTask; + /// + /// Invoked after the authentication before ClaimsIdentity is populated with claims retrieved through the LDAP connection. + /// This event is invoked when is set to true on . + /// + public Func OnRetrieveLdapClaims { get; set; } = context => Task.CompletedTask; + /// /// Invoked after the authentication is complete and a ClaimsIdentity has been generated. /// @@ -31,6 +37,11 @@ public class NegotiateEvents /// public virtual Task AuthenticationFailed(AuthenticationFailedContext context) => OnAuthenticationFailed(context); + /// + /// Invoked after the authentication before ClaimsIdentity is populated with claims retrieved through the LDAP connection. + /// + public virtual Task RetrieveLdapClaims(LdapContext context) => OnRetrieveLdapClaims(context); + /// /// Invoked after the authentication is complete and a ClaimsIdentity has been generated. /// diff --git a/src/Security/Authentication/Negotiate/src/Internal/LdapAdapter.cs b/src/Security/Authentication/Negotiate/src/Internal/LdapAdapter.cs new file mode 100644 index 000000000000..4ddad3c5e31b --- /dev/null +++ b/src/Security/Authentication/Negotiate/src/Internal/LdapAdapter.cs @@ -0,0 +1,97 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.DirectoryServices.Protocols; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.Authentication.Negotiate +{ + internal static class LdapAdapter + { + public static async Task RetrieveClaimsAsync(LdapSettings settings, ClaimsIdentity identity, ILogger logger) + { + var user = identity.Name; + var userAccountName = user.Substring(0, user.IndexOf('@')); + var distinguishedName = settings.Domain.Split('.').Select(name => $"dc={name}").Aggregate((a, b) => $"{a},{b}"); + + var filter = $"(&(objectClass=user)(sAMAccountName={userAccountName}))"; // This is using ldap search query language, it is looking on the server for someUser + var searchRequest = new SearchRequest(distinguishedName, filter, SearchScope.Subtree, null); + var searchResponse = (SearchResponse) await Task.Factory.FromAsync( + settings.LdapConnection.BeginSendRequest, + settings.LdapConnection.EndSendRequest, + searchRequest, + PartialResultProcessing.NoPartialResultSupport, + null); + + if (searchResponse.Entries.Count > 0) + { + if (searchResponse.Entries.Count > 1) + { + logger.LogWarning($"More than one response received for query: {filter} with distinguished name: {distinguishedName}"); + } + + var userFound = searchResponse.Entries[0]; //Get the object that was found on ldap + var memberof = userFound.Attributes["memberof"]; // You can access ldap Attributes with Attributes property + + foreach (var group in memberof) + { + // Example distinguished name: CN=TestGroup,DC=KERB,DC=local + var groupDN = $"{Encoding.UTF8.GetString((byte[])group)}"; + var groupCN = groupDN.Split(',')[0].Substring("CN=".Length); + + if (!settings.IgnoreNestedGroups) + { + GetNestedGroups(settings.LdapConnection, identity, distinguishedName, groupCN, logger); + } + else + { + AddRole(identity, groupCN); + } + } + } + else + { + logger.LogWarning($"No response received for query: {filter} with distinguished name: {distinguishedName}"); + } + } + + private static void GetNestedGroups(LdapConnection connection, ClaimsIdentity principal, string distinguishedName, string groupCN, ILogger logger) + { + var filter = $"(&(objectClass=group)(sAMAccountName={groupCN}))"; // This is using ldap search query language, it is looking on the server for someUser + var searchRequest = new SearchRequest(distinguishedName, filter, System.DirectoryServices.Protocols.SearchScope.Subtree, null); + var searchResponse = (SearchResponse)connection.SendRequest(searchRequest); + + if (searchResponse.Entries.Count > 0) + { + if (searchResponse.Entries.Count > 1) + { + logger.LogWarning($"More than one response received for query: {filter} with distinguished name: {distinguishedName}"); + } + + var group = searchResponse.Entries[0]; //Get the object that was found on ldap + string name = group.DistinguishedName; + AddRole(principal, name); + + var memberof = group.Attributes["memberof"]; // You can access ldap Attributes with Attributes property + if (memberof != null) + { + foreach (var member in memberof) + { + var groupDN = $"{Encoding.UTF8.GetString((byte[])member)}"; + var nestedGroupCN = groupDN.Split(',')[0].Substring("CN=".Length); + GetNestedGroups(connection, principal, distinguishedName, nestedGroupCN, logger); + } + } + } + } + + private static void AddRole(ClaimsIdentity identity, string role) + { + identity.AddClaim(new Claim(identity.RoleClaimType, role)); + } + } +} diff --git a/src/Security/Authentication/Negotiate/src/Internal/NegotiateOptionsValidationStartupFilter.cs b/src/Security/Authentication/Negotiate/src/Internal/NegotiateOptionsValidationStartupFilter.cs new file mode 100644 index 000000000000..429a57d81e90 --- /dev/null +++ b/src/Security/Authentication/Negotiate/src/Internal/NegotiateOptionsValidationStartupFilter.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Authentication.Negotiate.Internal +{ + internal class NegotiateOptionsValidationStartupFilter : IStartupFilter + { + private readonly string _authenticationScheme; + + public NegotiateOptionsValidationStartupFilter(string authenticationScheme) + { + _authenticationScheme = authenticationScheme; + } + + public Action Configure(Action next) + { + return builder => + { + // Resolve NegotiateOptions on startup to trigger post configuration and bind LdapConnection if needed + var options = builder.ApplicationServices.GetRequiredService>().Get(_authenticationScheme); + next(builder); + }; + } + } +} diff --git a/src/Security/Authentication/Negotiate/src/LdapSettings.cs b/src/Security/Authentication/Negotiate/src/LdapSettings.cs new file mode 100644 index 000000000000..1e26c26c14d4 --- /dev/null +++ b/src/Security/Authentication/Negotiate/src/LdapSettings.cs @@ -0,0 +1,75 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.DirectoryServices.Protocols; + +namespace Microsoft.AspNetCore.Authentication.Negotiate +{ + /// + /// Options class for configuring LDAP connections on Linux + /// + public class LdapSettings + { + /// + /// Configure whether LDAP connection should be used to resolve claims. + /// This is mainly used on Linux. + /// + public bool EnableLdapClaimResolution { get; set; } + + /// + /// The domain to use for the LDAP connection. This is a mandatory setting. + /// + /// + /// DOMAIN.com + /// + public string Domain { get; set; } + + /// + /// The machine account name to use when opening the LDAP connection. + /// If this is not provided, the machine wide credentials of the + /// domain joined machine will be used. + /// + public string MachineAccountName { get; set; } + + /// + /// The machine account password to use when opening the LDAP connection. + /// This must be provided if a is provided. + /// + public string MachineAccountPassword { get; set; } + + /// + /// This option indicates whether nested groups should be ignored when + /// resolving Roles. The default is false. + /// + public bool IgnoreNestedGroups { get; set; } + + /// + /// The to be used to retrieve role claims. + /// If no explicit connection is provided, an LDAP connection will be + /// automatically created based on the , + /// and + /// options. If provided, this connection will be used and the + /// , and + /// options will not be used to create + /// the . + /// + public LdapConnection LdapConnection { get; set; } + + public void Validate() + { + if (EnableLdapClaimResolution) + { + if (string.IsNullOrEmpty(Domain)) + { + throw new ArgumentException($"{nameof(EnableLdapClaimResolution)} is set to true but {nameof(Domain)} is not set."); + } + + if (string.IsNullOrEmpty(MachineAccountName) && !string.IsNullOrEmpty(MachineAccountPassword)) + { + throw new ArgumentException($"{nameof(MachineAccountPassword)} should only be specified when {nameof(MachineAccountName)} is configured."); + } + } + } + } +} diff --git a/src/Security/Authentication/Negotiate/src/Microsoft.AspNetCore.Authentication.Negotiate.csproj b/src/Security/Authentication/Negotiate/src/Microsoft.AspNetCore.Authentication.Negotiate.csproj index 265ffb533a11..c0aac839f5f7 100644 --- a/src/Security/Authentication/Negotiate/src/Microsoft.AspNetCore.Authentication.Negotiate.csproj +++ b/src/Security/Authentication/Negotiate/src/Microsoft.AspNetCore.Authentication.Negotiate.csproj @@ -10,7 +10,9 @@ + + diff --git a/src/Security/Authentication/Negotiate/src/NegotiateExtensions.cs b/src/Security/Authentication/Negotiate/src/NegotiateExtensions.cs index f5bbf8cbc860..e47417e17001 100644 --- a/src/Security/Authentication/Negotiate/src/NegotiateExtensions.cs +++ b/src/Security/Authentication/Negotiate/src/NegotiateExtensions.cs @@ -4,6 +4,8 @@ using System; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Negotiate; +using Microsoft.AspNetCore.Authentication.Negotiate.Internal; +using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; @@ -52,6 +54,7 @@ public static AuthenticationBuilder AddNegotiate(this AuthenticationBuilder buil public static AuthenticationBuilder AddNegotiate(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action configureOptions) { builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, PostConfigureNegotiateOptions>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton(new NegotiateOptionsValidationStartupFilter(authenticationScheme))); return builder.AddScheme(authenticationScheme, displayName, configureOptions); } } diff --git a/src/Security/Authentication/Negotiate/src/NegotiateHandler.cs b/src/Security/Authentication/Negotiate/src/NegotiateHandler.cs index 835542a42d5a..0ef6697857b4 100644 --- a/src/Security/Authentication/Negotiate/src/NegotiateHandler.cs +++ b/src/Security/Authentication/Negotiate/src/NegotiateHandler.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Runtime.InteropServices; using System.Security.Claims; using System.Security.Principal; using System.Text.Encodings.Web; @@ -324,10 +325,37 @@ protected override async Task HandleAuthenticateAsync() user = new ClaimsPrincipal(new ClaimsIdentity(identity)); } - var authenticatedContext = new AuthenticatedContext(Context, Scheme, Options) + AuthenticatedContext authenticatedContext; + + if (Options.LdapSettings.EnableLdapClaimResolution) { - Principal = user - }; + var ldapContext = new LdapContext(Context, Scheme, Options, Options.LdapSettings) + { + Principal = user + }; + + await Events.RetrieveLdapClaims(ldapContext); + + if (ldapContext.Result != null) + { + return ldapContext.Result; + } + + await LdapAdapter.RetrieveClaimsAsync(ldapContext.LdapSettings, ldapContext.Principal.Identity as ClaimsIdentity, Logger); + + authenticatedContext = new AuthenticatedContext(Context, Scheme, Options) + { + Principal = ldapContext.Principal + }; + } + else + { + authenticatedContext = new AuthenticatedContext(Context, Scheme, Options) + { + Principal = user + }; + } + await Events.Authenticated(authenticatedContext); if (authenticatedContext.Result != null) diff --git a/src/Security/Authentication/Negotiate/src/NegotiateOptions.cs b/src/Security/Authentication/Negotiate/src/NegotiateOptions.cs index 3f5d36b39f6d..40d090265c4b 100644 --- a/src/Security/Authentication/Negotiate/src/NegotiateOptions.cs +++ b/src/Security/Authentication/Negotiate/src/NegotiateOptions.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; + namespace Microsoft.AspNetCore.Authentication.Negotiate { /// @@ -33,6 +35,42 @@ public class NegotiateOptions : AuthenticationSchemeOptions /// public bool PersistNtlmCredentials { get; set; } = true; + /// + /// Configuration settings for LDAP connections used to retrieve claims. + /// This should only be used on Linux systems. + /// + internal LdapSettings LdapSettings { get; } = new LdapSettings(); + + /// + /// Use LDAP connections used to retrieve claims for the given domain. + /// This should only be used on Linux systems. + /// + public void EnableLdap(string domain) + { + if (string.IsNullOrEmpty(domain)) + { + throw new ArgumentNullException(nameof(domain)); + } + + LdapSettings.EnableLdapClaimResolution = true; + LdapSettings.Domain = domain; + } + + /// + /// Use LDAP connections used to retrieve claims using the configured settings. + /// This should only be used on Linux systems. + /// + public void EnableLdap(Action configureSettings) + { + if (configureSettings == null) + { + throw new ArgumentNullException(nameof(configureSettings)); + } + + LdapSettings.EnableLdapClaimResolution = true; + configureSettings(LdapSettings); + } + /// /// Indicates if integrated server Windows Auth is being used instead of this handler. /// See . diff --git a/src/Security/Authentication/Negotiate/src/PostConfigureNegotiateOptions.cs b/src/Security/Authentication/Negotiate/src/PostConfigureNegotiateOptions.cs index 91384c32932b..4fb8a29be41a 100644 --- a/src/Security/Authentication/Negotiate/src/PostConfigureNegotiateOptions.cs +++ b/src/Security/Authentication/Negotiate/src/PostConfigureNegotiateOptions.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.DirectoryServices.Protocols; using System.Linq; +using System.Net; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -59,6 +61,36 @@ public void PostConfigure(string name, NegotiateOptions options) + " Enable Windows Authentication for the server and the Negotiate Authentication handler will defer to it."); } } + + var ldapSettings = options.LdapSettings; + + if (ldapSettings.EnableLdapClaimResolution) + { + ldapSettings.Validate(); + + if (ldapSettings.LdapConnection == null) + { + var di = new LdapDirectoryIdentifier(server: ldapSettings.Domain, fullyQualifiedDnsHostName: true, connectionless: false); + + if (string.IsNullOrEmpty(ldapSettings.MachineAccountName)) + { + // Use default credentials + ldapSettings.LdapConnection = new LdapConnection(di); + } + else + { + // Use specific specific machine account + var machineAccount = ldapSettings.MachineAccountName + "@" + ldapSettings.Domain; + var credentials = new NetworkCredential(machineAccount, ldapSettings.MachineAccountPassword); + ldapSettings.LdapConnection = new LdapConnection(di, credentials); + } + + ldapSettings.LdapConnection.SessionOptions.ProtocolVersion = 3; //Setting LDAP Protocol to latest version + ldapSettings.LdapConnection.Timeout = TimeSpan.FromMinutes(1); + } + + ldapSettings.LdapConnection.Bind(); // This line actually makes the connection. + } } } } diff --git a/src/Security/Authentication/Negotiate/test/Negotiate.Test/EventTests.cs b/src/Security/Authentication/Negotiate/test/Negotiate.Test/EventTests.cs index 097964020752..af471a5450ed 100644 --- a/src/Security/Authentication/Negotiate/test/Negotiate.Test/EventTests.cs +++ b/src/Security/Authentication/Negotiate/test/Negotiate.Test/EventTests.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Reflection.Metadata; using System.Security.Principal; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; @@ -13,7 +12,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.TestHost; -using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Net.Http.Headers; @@ -371,6 +369,27 @@ public async Task OnAuthenticated_Fail_SuppresesCredentials() Assert.Equal(1, callCount); } + [Fact] + public async Task OnRetrieveLdapClaims_DoesNotFireWhenLdapDisabled() + { + var callCount = 0; + using var host = await CreateHostAsync(options => + { + options.Events = new NegotiateEvents() + { + OnRetrieveLdapClaims = context => + { + callCount++; + return Task.CompletedTask; + } + }; + }); + var server = host.GetTestServer(); + + await KerberosStage1And2Auth(server, new TestConnection()); + Assert.Equal(0, callCount); + } + private static async Task KerberosStage1And2Auth(TestServer server, TestConnection testConnection) { await KerberosStage1Auth(server, testConnection); diff --git a/src/Security/Authentication/Negotiate/test/Negotiate.Test/LdapSettingsValidationTests.cs b/src/Security/Authentication/Negotiate/test/Negotiate.Test/LdapSettingsValidationTests.cs new file mode 100644 index 000000000000..6a706d820bc1 --- /dev/null +++ b/src/Security/Authentication/Negotiate/test/Negotiate.Test/LdapSettingsValidationTests.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Xunit; + +namespace Microsoft.AspNetCore.Authentication.Negotiate.Test +{ + public class LdapSettingsValidationTests + { + [Fact] + public void EnabledWithoutDomainThrows() + { + var settings = new LdapSettings + { + EnableLdapClaimResolution = true + }; + + Assert.Throws(() => settings.Validate()); + } + + [Fact] + public void AccountPasswordWithoutAccountNameThrows() + { + var settings = new LdapSettings + { + EnableLdapClaimResolution = true, + MachineAccountPassword = "Passw0rd" + }; + + Assert.Throws(() => settings.Validate()); + } + } +} diff --git a/src/Security/Authentication/Negotiate/test/Negotiate.Test/ServerDeferralTests.cs b/src/Security/Authentication/Negotiate/test/Negotiate.Test/ServerDeferralTests.cs index efd513b829c1..f038c7ca806f 100644 --- a/src/Security/Authentication/Negotiate/test/Negotiate.Test/ServerDeferralTests.cs +++ b/src/Security/Authentication/Negotiate/test/Negotiate.Test/ServerDeferralTests.cs @@ -29,8 +29,7 @@ public async Task ServerDoesNotSupportAuth_NoError() [Fact] public async Task ServerSupportsAuthButDisabled_Error() { - using var host = await CreateHostAsync(supportsAuth: true, isEnabled: false); - var ex = Assert.Throws(() => host.Services.GetRequiredService>().Value); + var ex = await Assert.ThrowsAsync(async () => await CreateHostAsync(supportsAuth: true, isEnabled: false)); Assert.Equal("The Negotiate Authentication handler cannot be used on a server that directly supports Windows Authentication." + " Enable Windows Authentication for the server and the Negotiate Authentication handler will defer to it.", ex.Message); } From e2dd2969b58a0b84a4cec5f5a737cf78d757b072 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Wed, 26 Aug 2020 19:22:34 +0000 Subject: [PATCH 20/26] Set SameSiteMode for cookies in authentication tests (#25281) --- .../testassets/Wasm.Authentication.Server/Startup.cs | 6 ++++++ .../Wasm.Authentication.Server.csproj | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs b/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs index 1224ee978fdc..038e01f0c711 100644 --- a/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs +++ b/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -57,6 +58,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseWebAssemblyDebugging(); } + app.UseCookiePolicy(new CookiePolicyOptions + { + MinimumSameSitePolicy = SameSiteMode.Lax + }); + app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); diff --git a/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Wasm.Authentication.Server.csproj b/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Wasm.Authentication.Server.csproj index 142bfe2145f3..8daf5092666a 100644 --- a/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Wasm.Authentication.Server.csproj +++ b/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Wasm.Authentication.Server.csproj @@ -10,10 +10,12 @@ + + From 2916f4b09b0cf9e2075bee3fb934949dbae956ab Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Wed, 26 Aug 2020 12:56:56 -0700 Subject: [PATCH 21/26] Fixed server interop reliability tests (#25244) --- src/Components/Ignitor/src/BlazorClient.cs | 6 +++--- src/Components/Ignitor/src/CapturedJSInteropCall.cs | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Components/Ignitor/src/BlazorClient.cs b/src/Components/Ignitor/src/BlazorClient.cs index 5353659f3670..b19ab8b3dd5f 100644 --- a/src/Components/Ignitor/src/BlazorClient.cs +++ b/src/Components/Ignitor/src/BlazorClient.cs @@ -353,7 +353,7 @@ public async Task ConnectAsync(Uri uri, bool connectAutomatically = true, _hubConnection = builder.Build(); HubConnection.On("JS.AttachComponent", OnAttachComponent); - HubConnection.On("JS.BeginInvokeJS", OnBeginInvokeJS); + HubConnection.On("JS.BeginInvokeJS", OnBeginInvokeJS); HubConnection.On("JS.EndInvokeDotNet", OnEndInvokeDotNet); HubConnection.On("JS.RenderBatch", OnRenderBatch); HubConnection.On("JS.Error", OnError); @@ -401,9 +401,9 @@ private void OnAttachComponent(int componentId, string domSelector) NextAttachComponentReceived?.Completion?.TrySetResult(call); } - private void OnBeginInvokeJS(int asyncHandle, string identifier, string argsJson) + private void OnBeginInvokeJS(int asyncHandle, string identifier, string argsJson, int resultType, long targetInstanceId) { - var call = new CapturedJSInteropCall(asyncHandle, identifier, argsJson); + var call = new CapturedJSInteropCall(asyncHandle, identifier, argsJson, resultType, targetInstanceId); Operations?.JSInteropCalls.Enqueue(call); JSInterop?.Invoke(call); diff --git a/src/Components/Ignitor/src/CapturedJSInteropCall.cs b/src/Components/Ignitor/src/CapturedJSInteropCall.cs index 4af491a58abd..0dc8b0fa11a1 100644 --- a/src/Components/Ignitor/src/CapturedJSInteropCall.cs +++ b/src/Components/Ignitor/src/CapturedJSInteropCall.cs @@ -5,15 +5,19 @@ namespace Ignitor { public class CapturedJSInteropCall { - public CapturedJSInteropCall(int asyncHandle, string identifier, string argsJson) + public CapturedJSInteropCall(int asyncHandle, string identifier, string argsJson, int resultType, long targetInstanceId) { AsyncHandle = asyncHandle; Identifier = identifier; ArgsJson = argsJson; + ResultType = resultType; + TargetInstanceId = targetInstanceId; } public int AsyncHandle { get; } public string Identifier { get; } public string ArgsJson { get; } + public int ResultType { get; } + public long TargetInstanceId { get; } } } From f2b72b051166329d4c1f7a3aa5a6295883e2c334 Mon Sep 17 00:00:00 2001 From: Brennan Date: Wed, 26 Aug 2020 14:23:01 -0700 Subject: [PATCH 22/26] Fix SignalR typescript tests with Chrome SameSite reaction (#25283) * Fix Typescript tests * fixup --- .../clients/ts/FunctionalTests/Startup.cs | 18 +++++++++++++++--- .../clients/ts/FunctionalTests/ts/Common.ts | 12 ++++++++++++ .../ts/FunctionalTests/ts/ConnectionTests.ts | 14 ++++++++------ .../FunctionalTests/ts/HubConnectionTests.ts | 18 ++++-------------- 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/SignalR/clients/ts/FunctionalTests/Startup.cs b/src/SignalR/clients/ts/FunctionalTests/Startup.cs index 8a3ccfa767f7..a53eec75d204 100644 --- a/src/SignalR/clients/ts/FunctionalTests/Startup.cs +++ b/src/SignalR/clients/ts/FunctionalTests/Startup.cs @@ -163,9 +163,21 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger< { if (context.Request.Path.Value.Contains("/negotiate")) { - context.Response.Cookies.Append("testCookie", "testValue"); - context.Response.Cookies.Append("testCookie2", "testValue2"); - context.Response.Cookies.Append("expiredCookie", "doesntmatter", new CookieOptions() { Expires = DateTimeOffset.Now.AddHours(-1) }); + var cookieOptions = new CookieOptions(); + var expiredCookieOptions = new CookieOptions() { Expires = DateTimeOffset.Now.AddHours(-1) }; + if (context.Request.IsHttps) + { + cookieOptions.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None; + cookieOptions.Secure = true; + + expiredCookieOptions.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None; + expiredCookieOptions.Secure = true; + } + context.Response.Cookies.Append("testCookie", "testValue", cookieOptions); + context.Response.Cookies.Append("testCookie2", "testValue2", cookieOptions); + + cookieOptions.Expires = DateTimeOffset.Now.AddHours(-1); + context.Response.Cookies.Append("expiredCookie", "doesntmatter", expiredCookieOptions); } await next.Invoke(); diff --git a/src/SignalR/clients/ts/FunctionalTests/ts/Common.ts b/src/SignalR/clients/ts/FunctionalTests/ts/Common.ts index 668a73853633..4eb412145a48 100644 --- a/src/SignalR/clients/ts/FunctionalTests/ts/Common.ts +++ b/src/SignalR/clients/ts/FunctionalTests/ts/Common.ts @@ -60,6 +60,7 @@ console.log(`Using SignalR HTTPS Server: '${ENDPOINT_BASE_HTTPS_URL}'`); console.log(`Jasmine DEFAULT_TIMEOUT_INTERVAL: ${jasmine.DEFAULT_TIMEOUT_INTERVAL}`); export const ECHOENDPOINT_URL = ENDPOINT_BASE_URL + "/echo"; +export const HTTPS_ECHOENDPOINT_URL = ENDPOINT_BASE_HTTPS_URL + "/echo"; export function getHttpTransportTypes(): HttpTransportType[] { const transportTypes = []; @@ -131,3 +132,14 @@ export function eachHttpClient(action: (transport: HttpClient) => void) { return action(t); }); } + +// Run test in Node or Chrome, but not on macOS +export const shouldRunHttpsTests = + // Need to have an HTTPS URL + !!ENDPOINT_BASE_HTTPS_URL && + + // Run on Node, unless macOS + (process && process.platform !== "darwin") && + + // Only run under Chrome browser + (typeof navigator === "undefined" || navigator.userAgent.search("Chrome") !== -1); diff --git a/src/SignalR/clients/ts/FunctionalTests/ts/ConnectionTests.ts b/src/SignalR/clients/ts/FunctionalTests/ts/ConnectionTests.ts index b3445891b3f3..b377c98112c6 100644 --- a/src/SignalR/clients/ts/FunctionalTests/ts/ConnectionTests.ts +++ b/src/SignalR/clients/ts/FunctionalTests/ts/ConnectionTests.ts @@ -5,7 +5,7 @@ // tslint:disable:no-floating-promises import { HttpTransportType, IHttpConnectionOptions, TransferFormat } from "@microsoft/signalr"; -import { DEFAULT_TIMEOUT_INTERVAL, eachHttpClient, eachTransport, ECHOENDPOINT_URL } from "./Common"; +import { DEFAULT_TIMEOUT_INTERVAL, eachHttpClient, eachTransport, ECHOENDPOINT_URL, HTTPS_ECHOENDPOINT_URL, shouldRunHttpsTests } from "./Common"; import { TestLogger } from "./TestLogger"; // We want to continue testing HttpConnection, but we don't export it anymore. So just pull it in directly from the source file. @@ -15,6 +15,8 @@ import "./LogBannerReporter"; jasmine.DEFAULT_TIMEOUT_INTERVAL = DEFAULT_TIMEOUT_INTERVAL; +const USED_ECHOENDPOINT_URL = shouldRunHttpsTests ? HTTPS_ECHOENDPOINT_URL : ECHOENDPOINT_URL; + const commonOptions: IHttpConnectionOptions = { logMessageContent: true, logger: TestLogger.instance, @@ -23,7 +25,7 @@ const commonOptions: IHttpConnectionOptions = { describe("connection", () => { it("can connect to the server without specifying transport explicitly", (done) => { const message = "Hello World!"; - const connection = new HttpConnection(ECHOENDPOINT_URL, { + const connection = new HttpConnection(USED_ECHOENDPOINT_URL, { ...commonOptions, }); @@ -53,7 +55,7 @@ describe("connection", () => { const message = "Hello World!"; // the url should be resolved relative to the document.location.host // and the leading '/' should be automatically added to the url - const connection = new HttpConnection(ECHOENDPOINT_URL, { + const connection = new HttpConnection(USED_ECHOENDPOINT_URL, { ...commonOptions, httpClient, transport: transportType, @@ -83,7 +85,7 @@ describe("connection", () => { const message = "Hello World!"; // DON'T use commonOptions because we want to specifically test the scenario where logMessageContent is not set. - const connection = new HttpConnection(ECHOENDPOINT_URL, { + const connection = new HttpConnection(USED_ECHOENDPOINT_URL, { httpClient, logger: TestLogger.instance, transport: transportType, @@ -119,7 +121,7 @@ describe("connection", () => { const message = "Hello World!"; // DON'T use commonOptions because we want to specifically test the scenario where logMessageContent is set to true (even if commonOptions changes). - const connection = new HttpConnection(ECHOENDPOINT_URL, { + const connection = new HttpConnection(USED_ECHOENDPOINT_URL, { httpClient, logMessageContent: true, logger: TestLogger.instance, @@ -167,7 +169,7 @@ describe("connection", () => { const message = "Hello World!"; // The server will set some response headers for the '/negotiate' endpoint - const connection = new HttpConnection(ECHOENDPOINT_URL, { + const connection = new HttpConnection(USED_ECHOENDPOINT_URL, { ...commonOptions, httpClient, transport: transportType, diff --git a/src/SignalR/clients/ts/FunctionalTests/ts/HubConnectionTests.ts b/src/SignalR/clients/ts/FunctionalTests/ts/HubConnectionTests.ts index a802d7942446..600617d5f3cb 100644 --- a/src/SignalR/clients/ts/FunctionalTests/ts/HubConnectionTests.ts +++ b/src/SignalR/clients/ts/FunctionalTests/ts/HubConnectionTests.ts @@ -8,7 +8,7 @@ import { AbortError, DefaultHttpClient, HttpClient, HttpRequest, HttpResponse, H import { MessagePackHubProtocol } from "@microsoft/signalr-protocol-msgpack"; import { getUserAgentHeader, Platform } from "@microsoft/signalr/dist/esm/Utils"; -import { DEFAULT_TIMEOUT_INTERVAL, eachTransport, eachTransportAndProtocolAndHttpClient, ENDPOINT_BASE_HTTPS_URL, ENDPOINT_BASE_URL } from "./Common"; +import { DEFAULT_TIMEOUT_INTERVAL, eachTransport, eachTransportAndProtocolAndHttpClient, ENDPOINT_BASE_HTTPS_URL, ENDPOINT_BASE_URL, shouldRunHttpsTests } from "./Common"; import "./LogBannerReporter"; import { TestLogger } from "./TestLogger"; @@ -18,6 +18,7 @@ import * as RX from "rxjs"; const TESTHUBENDPOINT_URL = ENDPOINT_BASE_URL + "/testhub"; const TESTHUBENDPOINT_HTTPS_URL = ENDPOINT_BASE_HTTPS_URL ? (ENDPOINT_BASE_HTTPS_URL + "/testhub") : undefined; +const HTTPORHTTPS_TESTHUBENDPOINT_URL = shouldRunHttpsTests ? TESTHUBENDPOINT_HTTPS_URL : TESTHUBENDPOINT_URL; const TESTHUB_NOWEBSOCKETS_ENDPOINT_URL = ENDPOINT_BASE_URL + "/testhub-nowebsockets"; const TESTHUB_REDIRECT_ENDPOINT_URL = ENDPOINT_BASE_URL + "/redirect?numRedirects=0&baseUrl=" + ENDPOINT_BASE_URL; @@ -28,17 +29,6 @@ const commonOptions: IHttpConnectionOptions = { logMessageContent: true, }; -// Run test in Node or Chrome, but not on macOS -const shouldRunHttpsTests = - // Need to have an HTTPS URL - !!TESTHUBENDPOINT_HTTPS_URL && - - // Run on Node, unless macOS - (process && process.platform !== "darwin") && - - // Only run under Chrome browser - (typeof navigator === "undefined" || navigator.userAgent.search("Chrome") !== -1); - function getConnectionBuilder(transportType?: HttpTransportType, url?: string, options?: IHttpConnectionOptions): HubConnectionBuilder { let actualOptions: IHttpConnectionOptions = options || {}; if (transportType) { @@ -599,7 +589,7 @@ describe("hubConnection", () => { } it("preserves cookies between requests", async (done) => { - const hubConnection = getConnectionBuilder(transportType).build(); + const hubConnection = getConnectionBuilder(transportType, HTTPORHTTPS_TESTHUBENDPOINT_URL).build(); await hubConnection.start(); const cookieValue = await hubConnection.invoke("GetCookie", "testCookie"); const cookieValue2 = await hubConnection.invoke("GetCookie", "testCookie2"); @@ -610,7 +600,7 @@ describe("hubConnection", () => { }); it("expired cookies are not preserved", async (done) => { - const hubConnection = getConnectionBuilder(transportType).build(); + const hubConnection = getConnectionBuilder(transportType, HTTPORHTTPS_TESTHUBENDPOINT_URL).build(); await hubConnection.start(); const cookieValue = await hubConnection.invoke("GetCookie", "expiredCookie"); expect(cookieValue).toBeNull(); From bb769fe266e172478f9892f717aa0cd9725a522a Mon Sep 17 00:00:00 2001 From: Doug Bunting <6431421+dougbu@users.noreply.github.com> Date: Wed, 26 Aug 2020 23:12:48 -0700 Subject: [PATCH 23/26] [release/5.0] Reduce job timeouts in aspnetcore-quarantined-pr pipeline (#25300) --- .azure/pipelines/quarantined-pr.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.azure/pipelines/quarantined-pr.yml b/.azure/pipelines/quarantined-pr.yml index d6e4b61ed2fe..adcff0e3054a 100644 --- a/.azure/pipelines/quarantined-pr.yml +++ b/.azure/pipelines/quarantined-pr.yml @@ -28,7 +28,7 @@ jobs: jobName: Helix_quarantined_x64 jobDisplayName: 'Tests: Helix' agentOs: Windows - timeoutInMinutes: 240 + timeoutInMinutes: 120 steps: # Build the shared framework - script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log @@ -53,7 +53,7 @@ jobs: jobName: Windows_Quarantined_x64 jobDisplayName: 'Tests: Windows x64' agentOs: Windows - timeoutInMinutes: 240 + timeoutInMinutes: 90 isTestingJob: true steps: - powershell: "& ./build.ps1 -CI -nobl -all -pack -NoBuildJava" @@ -86,7 +86,7 @@ jobs: jobName: MacOS_Quarantined_Test jobDisplayName: "Tests: macOS 10.14" agentOs: macOS - timeoutInMinutes: 240 + timeoutInMinutes: 60 isTestingJob: true steps: - bash: ./build.sh --all --pack --ci --nobl --no-build-java @@ -119,7 +119,7 @@ jobs: jobName: Linux_Quarantined_Test jobDisplayName: "Tests: Ubuntu 16.04 x64" agentOs: Linux - timeoutInMinutes: 240 + timeoutInMinutes: 60 isTestingJob: true useHostedUbuntu: false steps: From 7b8fe5323407de28a2e9b76aa772179bcf6195d5 Mon Sep 17 00:00:00 2001 From: John Luo Date: Thu, 27 Aug 2020 13:16:01 -0700 Subject: [PATCH 24/26] Disable failing/hanging tests due to Chrome/Selenium issue (#25323) --- .../E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj | 3 +++ .../BlazorTemplates.Tests/BlazorTemplates.Tests.csproj | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj index a2fe529a1929..4a363519fb7b 100644 --- a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj +++ b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj @@ -14,6 +14,9 @@ true false + + true + diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj index 2da0e11666ef..6a024814c24f 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj @@ -10,6 +10,10 @@ true true + + + true + false true From e9a564d59944d1f8b900586edba0e6040f87210e Mon Sep 17 00:00:00 2001 From: Doug Bunting <6431421+dougbu@users.noreply.github.com> Date: Wed, 26 Aug 2020 23:12:36 -0700 Subject: [PATCH 25/26] [master] Reduce job timeouts in aspnetcore-quarantined-pr pipeline (#25301) --- .azure/pipelines/quarantined-pr.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.azure/pipelines/quarantined-pr.yml b/.azure/pipelines/quarantined-pr.yml index d6e4b61ed2fe..adcff0e3054a 100644 --- a/.azure/pipelines/quarantined-pr.yml +++ b/.azure/pipelines/quarantined-pr.yml @@ -28,7 +28,7 @@ jobs: jobName: Helix_quarantined_x64 jobDisplayName: 'Tests: Helix' agentOs: Windows - timeoutInMinutes: 240 + timeoutInMinutes: 120 steps: # Build the shared framework - script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log @@ -53,7 +53,7 @@ jobs: jobName: Windows_Quarantined_x64 jobDisplayName: 'Tests: Windows x64' agentOs: Windows - timeoutInMinutes: 240 + timeoutInMinutes: 90 isTestingJob: true steps: - powershell: "& ./build.ps1 -CI -nobl -all -pack -NoBuildJava" @@ -86,7 +86,7 @@ jobs: jobName: MacOS_Quarantined_Test jobDisplayName: "Tests: macOS 10.14" agentOs: macOS - timeoutInMinutes: 240 + timeoutInMinutes: 60 isTestingJob: true steps: - bash: ./build.sh --all --pack --ci --nobl --no-build-java @@ -119,7 +119,7 @@ jobs: jobName: Linux_Quarantined_Test jobDisplayName: "Tests: Ubuntu 16.04 x64" agentOs: Linux - timeoutInMinutes: 240 + timeoutInMinutes: 60 isTestingJob: true useHostedUbuntu: false steps: From 78271cfd45de075a353b1f33e0e6212118f156a7 Mon Sep 17 00:00:00 2001 From: John Luo Date: Thu, 27 Aug 2020 13:16:01 -0700 Subject: [PATCH 26/26] Disable failing/hanging tests due to Chrome/Selenium issue (#25323) --- .../E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj | 3 +++ .../BlazorTemplates.Tests/BlazorTemplates.Tests.csproj | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj index a2fe529a1929..4a363519fb7b 100644 --- a/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj +++ b/src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj @@ -14,6 +14,9 @@ true false + + true + diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj index 2da0e11666ef..6a024814c24f 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj @@ -10,6 +10,10 @@ true true + + + true + false true