From f7d2fac8a2d2818e4bfcb36e92b69c465161d2dc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 22 Jun 2020 12:11:55 -0700 Subject: [PATCH 001/100] Add support for optional FromBody parameters (#22634) * Add support for optional FromBody parameters Fixes https://github.com/dotnet/aspnetcore/issues/6878 * Fixup nullable * Changes per API review --- ....AspNetCore.Mvc.Abstractions.netcoreapp.cs | 8 ++++ .../ApiExplorer/ApiParameterDescription.cs | 5 ++ .../src/ModelBinding/BindingInfo.cs | 16 +++++++ .../src/ModelBinding/EmptyBodyBehavior.cs | 27 +++++++++++ .../IAllowEmptyInputInBodyModelBinding.cs | 10 ++++ .../src/DefaultApiDescriptionProvider.cs | 17 +++++-- .../test/DefaultApiDescriptionProviderTest.cs | 45 ++++++++++++++++-- ...icrosoft.AspNetCore.Mvc.Core.netcoreapp.cs | 1 + src/Mvc/Mvc.Core/src/FromBodyAttribute.cs | 12 ++++- .../ModelBinding/Binders/BodyModelBinder.cs | 6 +-- .../Binders/BodyModelBinderProvider.cs | 20 +++++++- .../Binders/BodyModelBinderProviderTest.cs | 47 +++++++++++++++++++ .../Binders/BodyModelBinderTests.cs | 7 ++- .../InputFormatterTests.cs | 34 ++++++++++++-- .../Controllers/HomeController.cs | 9 ++++ 15 files changed, 245 insertions(+), 19 deletions(-) create mode 100644 src/Mvc/Mvc.Abstractions/src/ModelBinding/EmptyBodyBehavior.cs create mode 100644 src/Mvc/Mvc.Abstractions/src/ModelBinding/IAllowEmptyInputInBodyModelBinding.cs diff --git a/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.netcoreapp.cs b/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.netcoreapp.cs index f60d50cb40..84ca15ad39 100644 --- a/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.netcoreapp.cs +++ b/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.netcoreapp.cs @@ -160,6 +160,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer public partial class ApiParameterDescription { public ApiParameterDescription() { } + public Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo BindingInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public object DefaultValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool IsRequired { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata ModelMetadata { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } @@ -462,6 +463,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public string BinderModelName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Type BinderType { get { throw null; } set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public Microsoft.AspNetCore.Mvc.ModelBinding.EmptyBodyBehavior EmptyBodyBehavior { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider PropertyFilterProvider { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Func RequestPredicate { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public static Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo GetBindingInfo(System.Collections.Generic.IEnumerable attributes) { throw null; } @@ -500,6 +502,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public override bool CanAcceptDataFrom(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource bindingSource) { throw null; } public static Microsoft.AspNetCore.Mvc.ModelBinding.CompositeBindingSource Create(System.Collections.Generic.IEnumerable bindingSources, string displayName) { throw null; } } + public enum EmptyBodyBehavior + { + Default = 0, + Allow = 1, + Disallow = 2, + } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct EnumGroupAndName { diff --git a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterDescription.cs b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterDescription.cs index f020c6361a..17f499c1f0 100644 --- a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterDescription.cs +++ b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterDescription.cs @@ -32,6 +32,11 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// public BindingSource Source { get; set; } + /// + /// Gets or sets the . + /// + public BindingInfo BindingInfo { get; set; } + /// /// Gets or sets the parameter type. /// diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingInfo.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingInfo.cs index cfa796ab75..38fbc894a9 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingInfo.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingInfo.cs @@ -38,6 +38,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding BinderType = other.BinderType; PropertyFilterProvider = other.PropertyFilterProvider; RequestPredicate = other.RequestPredicate; + EmptyBodyBehavior = other.EmptyBodyBehavior; } /// @@ -87,6 +88,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// public Func RequestPredicate { get; set; } + /// + /// Gets or sets the value which decides if empty bodies are treated as valid inputs. + /// + public EmptyBodyBehavior EmptyBodyBehavior { get; set; } + /// /// Constructs a new instance of from the given . /// @@ -160,6 +166,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } } + foreach (var configureEmptyBodyBehavior in attributes.OfType()) + { + isBindingInfoPresent = true; + bindingInfo.EmptyBodyBehavior = configureEmptyBodyBehavior.EmptyBodyBehavior; + break; + } + return isBindingInfoPresent ? bindingInfo : null; } @@ -235,6 +248,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding PropertyFilterProvider = modelMetadata.PropertyFilterProvider; } + // There isn't a ModelMetadata feature to configure AllowEmptyInputInBodyModelBinding, + // so nothing to infer from it. + return isBindingInfoPresent; } diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/EmptyBodyBehavior.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/EmptyBodyBehavior.cs new file mode 100644 index 0000000000..4e3a062d5e --- /dev/null +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/EmptyBodyBehavior.cs @@ -0,0 +1,27 @@ +// 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.ModelBinding +{ + /// + /// Determines the behavior for processing empty bodies during input formatting. + /// + public enum EmptyBodyBehavior + { + /// + /// Uses the framework default behavior for processing empty bodies. + /// This is typically configured using MvcOptions.AllowEmptyInputInBodyModelBinding + /// + Default, + + /// + /// Empty bodies are treated as valid inputs. + /// + Allow, + + /// + /// Empty bodies are treated as invalid inputs. + /// + Disallow, + } +} diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/IAllowEmptyInputInBodyModelBinding.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/IAllowEmptyInputInBodyModelBinding.cs new file mode 100644 index 0000000000..3184da3e5b --- /dev/null +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/IAllowEmptyInputInBodyModelBinding.cs @@ -0,0 +1,10 @@ +// 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.ModelBinding +{ + internal interface IConfigureEmptyBodyBehavior + { + public EmptyBodyBehavior EmptyBodyBehavior { get; } + } +} diff --git a/src/Mvc/Mvc.ApiExplorer/src/DefaultApiDescriptionProvider.cs b/src/Mvc/Mvc.ApiExplorer/src/DefaultApiDescriptionProvider.cs index d44d801bd9..bbc1f86ef1 100644 --- a/src/Mvc/Mvc.ApiExplorer/src/DefaultApiDescriptionProvider.cs +++ b/src/Mvc/Mvc.ApiExplorer/src/DefaultApiDescriptionProvider.cs @@ -222,7 +222,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer ProcessRouteParameters(context); // Set IsRequired=true - ProcessIsRequired(context); + ProcessIsRequired(context, _mvcOptions); // Set DefaultValue ProcessParameterDefaultValue(context); @@ -273,13 +273,20 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer } } - internal static void ProcessIsRequired(ApiParameterContext context) + internal static void ProcessIsRequired(ApiParameterContext context, MvcOptions mvcOptions) { foreach (var parameter in context.Results) { if (parameter.Source == BindingSource.Body) { - parameter.IsRequired = true; + if (parameter.BindingInfo == null || parameter.BindingInfo.EmptyBodyBehavior == EmptyBodyBehavior.Default) + { + parameter.IsRequired = !mvcOptions.AllowEmptyInputInBodyModelBinding; + } + else + { + parameter.IsRequired = !(parameter.BindingInfo.EmptyBodyBehavior == EmptyBodyBehavior.Allow); + } } if (parameter.ModelMetadata != null && parameter.ModelMetadata.IsBindingRequired) @@ -466,6 +473,8 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer public string PropertyName { get; set; } + public BindingInfo BindingInfo { get; set; } + public static ApiParameterDescriptionContext GetContext( ModelMetadata metadata, BindingInfo bindingInfo, @@ -478,6 +487,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer BinderModelName = bindingInfo?.BinderModelName, BindingSource = bindingInfo?.BindingSource, PropertyName = propertyName ?? metadata.Name, + BindingInfo = bindingInfo, }; } } @@ -607,6 +617,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer Source = source, Type = bindingContext.ModelMetadata.ModelType, ParameterDescriptor = Parameter, + BindingInfo = bindingContext.BindingInfo }; } diff --git a/src/Mvc/Mvc.ApiExplorer/test/DefaultApiDescriptionProviderTest.cs b/src/Mvc/Mvc.ApiExplorer/test/DefaultApiDescriptionProviderTest.cs index 121b21d47a..332a9d2cfc 100644 --- a/src/Mvc/Mvc.ApiExplorer/test/DefaultApiDescriptionProviderTest.cs +++ b/src/Mvc/Mvc.ApiExplorer/test/DefaultApiDescriptionProviderTest.cs @@ -1725,12 +1725,47 @@ namespace Microsoft.AspNetCore.Mvc.Description var context = GetApiParameterContext(description); // Act - DefaultApiDescriptionProvider.ProcessIsRequired(context); + DefaultApiDescriptionProvider.ProcessIsRequired(context, new MvcOptions()); // Assert Assert.True(description.IsRequired); } + [Fact] + public void ProcessIsRequired_SetsFalse_IfAllowEmptyInputInBodyModelBinding_IsSetInMvcOptions() + { + // Arrange + var description = new ApiParameterDescription { Source = BindingSource.Body, }; + var context = GetApiParameterContext(description); + + // Act + DefaultApiDescriptionProvider.ProcessIsRequired(context, new MvcOptions { AllowEmptyInputInBodyModelBinding = true }); + + // Assert + Assert.False(description.IsRequired); + } + + [Fact] + public void ProcessIsRequired_SetsFalse_IfEmptyBodyBehaviorIsAllowedInBindingInfo() + { + // Arrange + var description = new ApiParameterDescription + { + Source = BindingSource.Body, + BindingInfo = new BindingInfo + { + EmptyBodyBehavior = EmptyBodyBehavior.Allow, + } + }; + var context = GetApiParameterContext(description); + + // Act + DefaultApiDescriptionProvider.ProcessIsRequired(context, new MvcOptions()); + + // Assert + Assert.False(description.IsRequired); + } + [Fact] public void ProcessIsRequired_SetsTrue_ForParameterDescriptorsWithBindRequired() { @@ -1747,7 +1782,7 @@ namespace Microsoft.AspNetCore.Mvc.Description description.ModelMetadata = modelMetadataProvider.GetMetadataForProperty(typeof(Person), nameof(Person.Name)); // Act - DefaultApiDescriptionProvider.ProcessIsRequired(context); + DefaultApiDescriptionProvider.ProcessIsRequired(context, new MvcOptions()); // Assert Assert.True(description.IsRequired); @@ -1765,7 +1800,7 @@ namespace Microsoft.AspNetCore.Mvc.Description var context = GetApiParameterContext(description); // Act - DefaultApiDescriptionProvider.ProcessIsRequired(context); + DefaultApiDescriptionProvider.ProcessIsRequired(context, new MvcOptions()); // Assert Assert.True(description.IsRequired); @@ -1779,7 +1814,7 @@ namespace Microsoft.AspNetCore.Mvc.Description var context = GetApiParameterContext(description); // Act - DefaultApiDescriptionProvider.ProcessIsRequired(context); + DefaultApiDescriptionProvider.ProcessIsRequired(context, new MvcOptions()); // Assert Assert.False(description.IsRequired); @@ -1798,7 +1833,7 @@ namespace Microsoft.AspNetCore.Mvc.Description description.ModelMetadata = modelMetadataProvider.GetMetadataForProperty(typeof(Person), nameof(Person.Name)); // Act - DefaultApiDescriptionProvider.ProcessIsRequired(context); + DefaultApiDescriptionProvider.ProcessIsRequired(context, new MvcOptions()); // Assert Assert.False(description.IsRequired); diff --git a/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp.cs b/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp.cs index d4672abb31..0e3186b36f 100644 --- a/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp.cs +++ b/src/Mvc/Mvc.Core/ref/Microsoft.AspNetCore.Mvc.Core.netcoreapp.cs @@ -745,6 +745,7 @@ namespace Microsoft.AspNetCore.Mvc { public FromBodyAttribute() { } public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get { throw null; } } + public Microsoft.AspNetCore.Mvc.ModelBinding.EmptyBodyBehavior EmptyBodyBehavior { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } [System.AttributeUsageAttribute(System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] public partial class FromFormAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider diff --git a/src/Mvc/Mvc.Core/src/FromBodyAttribute.cs b/src/Mvc/Mvc.Core/src/FromBodyAttribute.cs index 157d1cdd3d..9894666c7d 100644 --- a/src/Mvc/Mvc.Core/src/FromBodyAttribute.cs +++ b/src/Mvc/Mvc.Core/src/FromBodyAttribute.cs @@ -10,9 +10,19 @@ namespace Microsoft.AspNetCore.Mvc /// Specifies that a parameter or property should be bound using the request body. /// [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public class FromBodyAttribute : Attribute, IBindingSourceMetadata + public class FromBodyAttribute : Attribute, IBindingSourceMetadata, IConfigureEmptyBodyBehavior { /// public BindingSource BindingSource => BindingSource.Body; + + /// + /// Gets or sets a value which decides whether body model binding should treat empty + /// input as valid. + /// + /// + /// The default behavior is to use framework defaults as configured by . + /// Specifying or will override the framework defaults. + /// + public EmptyBodyBehavior EmptyBodyBehavior { get; set; } } } diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/BodyModelBinder.cs b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/BodyModelBinder.cs index 5b036b844d..6b21cf751d 100644 --- a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/BodyModelBinder.cs +++ b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/BodyModelBinder.cs @@ -91,6 +91,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders _options = options; } + internal bool AllowEmptyBody { get; set; } + /// public async Task BindModelAsync(ModelBindingContext bindingContext) { @@ -116,15 +118,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var httpContext = bindingContext.HttpContext; - var allowEmptyInputInModelBinding = _options?.AllowEmptyInputInBodyModelBinding == true; - var formatterContext = new InputFormatterContext( httpContext, modelBindingKey, bindingContext.ModelState, bindingContext.ModelMetadata, _readerFactory, - allowEmptyInputInModelBinding); + AllowEmptyBody); var formatter = (IInputFormatter)null; for (var i = 0; i < _formatters.Count; i++) diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/BodyModelBinderProvider.cs b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/BodyModelBinderProvider.cs index c2110c793e..cf3c583e9b 100644 --- a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/BodyModelBinderProvider.cs +++ b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/BodyModelBinderProvider.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// The list of . /// The . public BodyModelBinderProvider(IList formatters, IHttpRequestStreamReaderFactory readerFactory) - : this(formatters, readerFactory, loggerFactory: null) + : this(formatters, readerFactory, loggerFactory: NullLoggerFactory.Instance) { } @@ -89,10 +90,25 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders typeof(IInputFormatter).FullName)); } - return new BodyModelBinder(_formatters, _readerFactory, _loggerFactory, _options); + var treatEmptyInputAsDefaultValue = CalculateAllowEmptyBody(context.BindingInfo.EmptyBodyBehavior, _options); + + return new BodyModelBinder(_formatters, _readerFactory, _loggerFactory, _options) + { + AllowEmptyBody = treatEmptyInputAsDefaultValue, + }; } return null; } + + internal static bool CalculateAllowEmptyBody(EmptyBodyBehavior emptyBodyBehavior, MvcOptions options) + { + if (emptyBodyBehavior == EmptyBodyBehavior.Default) + { + return options?.AllowEmptyInputInBodyModelBinding ?? false; + } + + return emptyBodyBehavior == EmptyBodyBehavior.Allow; + } } } diff --git a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/BodyModelBinderProviderTest.cs b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/BodyModelBinderProviderTest.cs index 22a6d69a66..148af531be 100644 --- a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/BodyModelBinderProviderTest.cs +++ b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/BodyModelBinderProviderTest.cs @@ -86,6 +86,53 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders provider.GetBinder(context); } + [Fact] + public void CalculateAllowEmptyBody_EmptyBodyBehaviorIsDefaultValue_UsesMvcOptions() + { + // Arrange + var options = new MvcOptions { AllowEmptyInputInBodyModelBinding = true }; + + // Act + var allowEmpty = BodyModelBinderProvider.CalculateAllowEmptyBody(EmptyBodyBehavior.Default, options); + + // Assert + Assert.True(allowEmpty); + } + + [Fact] + public void CalculateAllowEmptyBody_EmptyBodyBehaviorIsDefaultValue_DefaultsToFalseWhenOptionsIsUnavailable() + { + // Act + var allowEmpty = BodyModelBinderProvider.CalculateAllowEmptyBody(EmptyBodyBehavior.Default, options: null); + + // Assert + Assert.False(allowEmpty); + } + + [Fact] + public void CalculateAllowEmptyBody_EmptyBodyBehaviorIsAllow() + { + // Act + var allowEmpty = BodyModelBinderProvider.CalculateAllowEmptyBody(EmptyBodyBehavior.Allow, options: new MvcOptions()); + + // Assert + Assert.True(allowEmpty); + } + + [Fact] + public void CalculateAllowEmptyBody_EmptyBodyBehaviorIsDisallowed() + { + // Arrange + // MvcOptions.AllowEmptyInputInBodyModelBinding should be ignored if EmptyBodyBehavior disallows it + var options = new MvcOptions { AllowEmptyInputInBodyModelBinding = true }; + + // Act + var allowEmpty = BodyModelBinderProvider.CalculateAllowEmptyBody(EmptyBodyBehavior.Disallow, options); + + // Assert + Assert.False(allowEmpty); + } + private static BodyModelBinderProvider CreateProvider(params IInputFormatter[] formatters) { var sink = new TestSink(); diff --git a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/BodyModelBinderTests.cs b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/BodyModelBinderTests.cs index ffdf5733d8..6aaf585aec 100644 --- a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/BodyModelBinderTests.cs +++ b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/BodyModelBinderTests.cs @@ -657,8 +657,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders private static BodyModelBinder CreateBinder(IList formatters, bool treatEmptyInputAsDefaultValueOption = false) { - var options = new MvcOptions { AllowEmptyInputInBodyModelBinding = treatEmptyInputAsDefaultValueOption }; - return CreateBinder(formatters, options); + var options = new MvcOptions(); + var binder = CreateBinder(formatters, options); + binder.AllowEmptyBody = treatEmptyInputAsDefaultValueOption; + + return binder; } private static BodyModelBinder CreateBinder(IList formatters, MvcOptions mvcOptions) diff --git a/src/Mvc/test/Mvc.FunctionalTests/InputFormatterTests.cs b/src/Mvc/test/Mvc.FunctionalTests/InputFormatterTests.cs index 699c1010f1..0283623d1a 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/InputFormatterTests.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/InputFormatterTests.cs @@ -3,8 +3,10 @@ using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Text; using System.Threading.Tasks; +using FormatterWebSite.Controllers; using FormatterWebSite.Models; using Microsoft.AspNetCore.Testing; using Newtonsoft.Json; @@ -22,9 +24,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests public HttpClient Client { get; } - [ConditionalFact] - // Mono issue - https://github.com/aspnet/External/issues/18 - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [Fact] public async Task CheckIfXmlInputFormatterIsBeingCalled() { // Arrange @@ -168,5 +168,33 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal("The DerivedProperty field is required.", value.First); }); } + + [Fact] + public async Task BodyIsRequiredByDefault() + { + // Act + var response = await Client.PostAsJsonAsync($"Home/{nameof(HomeController.DefaultBody)}", value: null); + + // Assert + await response.AssertStatusCodeAsync(HttpStatusCode.BadRequest); + var problemDetails = await response.Content.ReadFromJsonAsync(); + Assert.Collection( + problemDetails.Errors, + kvp => + { + Assert.Empty(kvp.Key); + Assert.Equal("A non-empty request body is required.", Assert.Single(kvp.Value)); + }); + } + + [Fact] + public async Task OptionalFromBodyWorks() + { + // Act + var response = await Client.PostAsJsonAsync($"Home/{nameof(HomeController.OptionalBody)}", value: null); + + // Assert + await response.AssertStatusCodeAsync(HttpStatusCode.OK); + } } } diff --git a/src/Mvc/test/WebSites/FormatterWebSite/Controllers/HomeController.cs b/src/Mvc/test/WebSites/FormatterWebSite/Controllers/HomeController.cs index 8f46f63571..4258cac153 100644 --- a/src/Mvc/test/WebSites/FormatterWebSite/Controllers/HomeController.cs +++ b/src/Mvc/test/WebSites/FormatterWebSite/Controllers/HomeController.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding; namespace FormatterWebSite.Controllers { @@ -34,5 +35,13 @@ namespace FormatterWebSite.Controllers SampleIntInDerived = 50 }; } + + [HttpPost] + public IActionResult DefaultBody([FromBody] DummyClass dummy) + => ModelState.IsValid ? Ok() : ValidationProblem(); + + [HttpPost] + public IActionResult OptionalBody([FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] DummyClass dummy) + => ModelState.IsValid ? Ok() : ValidationProblem(); } } \ No newline at end of file From b669497be51b3cff683eebdc6abc74098fee4e58 Mon Sep 17 00:00:00 2001 From: Doug Bunting <6431421+dougbu@users.noreply.github.com> Date: Mon, 22 Jun 2020 12:20:56 -0700 Subject: [PATCH 002/100] Update branding to Preview8 (#23225) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 7c793eaa5f..cd52d9be9e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -9,7 +9,7 @@ 5 0 0 - 7 + 8 From efeb8508dcde5ce265b2bc08c6dbec1192fe4151 Mon Sep 17 00:00:00 2001 From: ccvca Date: Mon, 22 Jun 2020 22:26:30 +0200 Subject: [PATCH 003/100] Fix: 'https://' is also supported as scheme. (#23194) --- src/Servers/Kestrel/Core/src/CoreStrings.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Servers/Kestrel/Core/src/CoreStrings.resx b/src/Servers/Kestrel/Core/src/CoreStrings.resx index 96f6e49969..46f2e263a3 100644 --- a/src/Servers/Kestrel/Core/src/CoreStrings.resx +++ b/src/Servers/Kestrel/Core/src/CoreStrings.resx @@ -268,7 +268,7 @@ Overriding endpoints defined in UseKestrel() because {settingName} is set to true. Binding to address(es) '{addresses}' instead. - Unrecognized scheme in server address '{address}'. Only 'http://' is supported. + Unrecognized scheme in server address '{address}'. Only 'http://' and 'https://' are supported. Headers are read-only, response has already started. From ce8096545464e946340bb81f8b9818ef1d8a798e Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 23 Jun 2020 09:20:06 +1200 Subject: [PATCH 004/100] HPackDecoder performance (#23083) --- .../src/Internal/Http2/HPackHeaderWriter.cs | 2 +- .../HPackDecoderBenchmark.cs | 135 +++++ .../runtime/Http2/Hpack/DynamicTable.cs | 4 +- .../runtime/Http2/Hpack/H2StaticTable.cs | 27 +- .../runtime/Http2/Hpack/HPackDecoder.cs | 545 +++++++++++------- .../runtime/Http2/Hpack/HPackEncoder.cs | 2 +- .../runtime/Http2/HPackDecoderTest.cs | 233 +++++--- 7 files changed, 661 insertions(+), 287 deletions(-) create mode 100644 src/Servers/Kestrel/perf/Kestrel.Performance/HPackDecoderBenchmark.cs diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/HPackHeaderWriter.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/HPackHeaderWriter.cs index 33c7b920f3..c914595bc9 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/HPackHeaderWriter.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/HPackHeaderWriter.cs @@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 case 404: case 500: // Status codes which exist in the HTTP/2 StaticTable. - return HPackEncoder.EncodeIndexedHeaderField(H2StaticTable.StatusIndex[statusCode], buffer, out length); + return HPackEncoder.EncodeIndexedHeaderField(H2StaticTable.GetStatusIndex(statusCode), buffer, out length); default: const string name = ":status"; var value = StatusCodes.ToStatusString(statusCode); diff --git a/src/Servers/Kestrel/perf/Kestrel.Performance/HPackDecoderBenchmark.cs b/src/Servers/Kestrel/perf/Kestrel.Performance/HPackDecoderBenchmark.cs new file mode 100644 index 0000000000..31382bbf5e --- /dev/null +++ b/src/Servers/Kestrel/perf/Kestrel.Performance/HPackDecoderBenchmark.cs @@ -0,0 +1,135 @@ +// 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.Linq; +using System.Net.Http.HPack; +using System.Text; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; + +namespace Microsoft.AspNetCore.Server.Kestrel.Performance +{ + public class HPackDecoderBenchmark + { + // Indexed Header Field Representation - Dynamic Table - Index 62 (first index in dynamic table) + private static readonly byte[] _indexedHeaderDynamic = new byte[] { 0xbe }; + + private static readonly byte[] _literalHeaderFieldWithoutIndexingNewName = new byte[] { 0x00 }; + + private const string _headerNameString = "new-header"; + + private static readonly byte[] _headerNameBytes = Encoding.ASCII.GetBytes(_headerNameString); + + private static readonly byte[] _headerName = new byte[] { (byte)_headerNameBytes.Length } + .Concat(_headerNameBytes) + .ToArray(); + + private const string _headerValueString = "value"; + + private static readonly byte[] _headerValueBytes = Encoding.ASCII.GetBytes(_headerValueString); + + private static readonly byte[] _headerValue = new byte[] { (byte)_headerValueBytes.Length } + .Concat(_headerValueBytes) + .ToArray(); + + private static readonly byte[] _literalHeaderFieldNeverIndexed_NewName = _literalHeaderFieldWithoutIndexingNewName + .Concat(_headerName) + .Concat(_headerValue) + .ToArray(); + + private static readonly byte[] _literalHeaderFieldNeverIndexed_NewName_Large; + private static readonly byte[] _literalHeaderFieldNeverIndexed_NewName_Multiple; + private static readonly byte[] _indexedHeaderDynamic_Multiple; + + static HPackDecoderBenchmark() + { + string string8193 = new string('a', 8193); + + _literalHeaderFieldNeverIndexed_NewName_Large = _literalHeaderFieldWithoutIndexingNewName + .Concat(new byte[] { 0x7f, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix, no Huffman encoding + .Concat(Encoding.ASCII.GetBytes(string8193)) + .Concat(new byte[] { 0x7f, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix, no Huffman encoding + .Concat(Encoding.ASCII.GetBytes(string8193)) + .ToArray(); + + _literalHeaderFieldNeverIndexed_NewName_Multiple = _literalHeaderFieldNeverIndexed_NewName + .Concat(_literalHeaderFieldNeverIndexed_NewName) + .Concat(_literalHeaderFieldNeverIndexed_NewName) + .Concat(_literalHeaderFieldNeverIndexed_NewName) + .Concat(_literalHeaderFieldNeverIndexed_NewName) + .ToArray(); + + _indexedHeaderDynamic_Multiple = _indexedHeaderDynamic + .Concat(_indexedHeaderDynamic) + .Concat(_indexedHeaderDynamic) + .Concat(_indexedHeaderDynamic) + .Concat(_indexedHeaderDynamic) + .ToArray(); + } + + private HPackDecoder _decoder; + private TestHeadersHandler _testHeadersHandler; + private DynamicTable _dynamicTable; + + [GlobalSetup] + public void GlobalSetup() + { + _dynamicTable = new DynamicTable(maxSize: 4096); + _dynamicTable.Insert(_headerNameBytes, _headerValueBytes); + _decoder = new HPackDecoder(maxDynamicTableSize: 4096, maxHeadersLength: 65536, _dynamicTable); + _testHeadersHandler = new TestHeadersHandler(); + } + + [Benchmark] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName() + { + _decoder.Decode(_literalHeaderFieldNeverIndexed_NewName, endHeaders: true, handler: _testHeadersHandler); + } + + [Benchmark] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_Large() + { + _decoder.Decode(_literalHeaderFieldNeverIndexed_NewName_Large, endHeaders: true, handler: _testHeadersHandler); + } + + [Benchmark] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_Multiple() + { + _decoder.Decode(_literalHeaderFieldNeverIndexed_NewName_Multiple, endHeaders: true, handler: _testHeadersHandler); + } + + [Benchmark] + public void DecodesIndexedHeaderField_DynamicTable() + { + _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: _testHeadersHandler); + } + + [Benchmark] + public void DecodesIndexedHeaderField_DynamicTable_Multiple() + { + _decoder.Decode(_indexedHeaderDynamic_Multiple, endHeaders: true, handler: _testHeadersHandler); + } + + private class TestHeadersHandler : IHttpHeadersHandler + { + public void OnHeader(ReadOnlySpan name, ReadOnlySpan value) + { + } + + public void OnHeadersComplete(bool endStream) + { + } + + public void OnStaticIndexedHeader(int index) + { + } + + public void OnStaticIndexedHeader(int index, ReadOnlySpan value) + { + } + } + } +} diff --git a/src/Shared/runtime/Http2/Hpack/DynamicTable.cs b/src/Shared/runtime/Http2/Hpack/DynamicTable.cs index 5a8fdf170f..9e93dca87c 100644 --- a/src/Shared/runtime/Http2/Hpack/DynamicTable.cs +++ b/src/Shared/runtime/Http2/Hpack/DynamicTable.cs @@ -25,7 +25,7 @@ namespace System.Net.Http.HPack public int MaxSize => _maxSize; - public HeaderField this[int index] + public ref readonly HeaderField this[int index] { get { @@ -42,7 +42,7 @@ namespace System.Net.Http.HPack index += _buffer.Length; } - return _buffer[index]; + return ref _buffer[index]; } } diff --git a/src/Shared/runtime/Http2/Hpack/H2StaticTable.cs b/src/Shared/runtime/Http2/Hpack/H2StaticTable.cs index 7f3b775582..c0f203fef4 100644 --- a/src/Shared/runtime/Http2/Hpack/H2StaticTable.cs +++ b/src/Shared/runtime/Http2/Hpack/H2StaticTable.cs @@ -9,23 +9,22 @@ namespace System.Net.Http.HPack { internal static class H2StaticTable { - // Index of status code into s_staticDecoderTable - private static readonly Dictionary s_statusIndex = new Dictionary - { - [200] = 8, - [204] = 9, - [206] = 10, - [304] = 11, - [400] = 12, - [404] = 13, - [500] = 14, - }; - public static int Count => s_staticDecoderTable.Length; - public static HeaderField Get(int index) => s_staticDecoderTable[index]; + public static ref readonly HeaderField Get(int index) => ref s_staticDecoderTable[index]; - public static IReadOnlyDictionary StatusIndex => s_statusIndex; + public static int GetStatusIndex(int status) => + status switch + { + 200 => 8, + 204 => 9, + 206 => 10, + 304 => 11, + 400 => 12, + 404 => 13, + 500 => 14, + _ => throw new ArgumentOutOfRangeException() + }; private static readonly HeaderField[] s_staticDecoderTable = new HeaderField[] { diff --git a/src/Shared/runtime/Http2/Hpack/HPackDecoder.cs b/src/Shared/runtime/Http2/Hpack/HPackDecoder.cs index 3fe3c86243..b07dc47d9a 100644 --- a/src/Shared/runtime/Http2/Hpack/HPackDecoder.cs +++ b/src/Shared/runtime/Http2/Hpack/HPackDecoder.cs @@ -5,6 +5,7 @@ #nullable enable using System.Buffers; using System.Diagnostics; +using System.Numerics; #if KESTREL using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; #endif @@ -37,7 +38,6 @@ namespace System.Net.Http.HPack // | 1 | Index (7+) | // +---+---------------------------+ private const byte IndexedHeaderFieldMask = 0x80; - private const byte IndexedHeaderFieldRepresentation = 0x80; // http://httpwg.org/specs/rfc7541.html#rfc.section.6.2.1 // 0 1 2 3 4 5 6 7 @@ -45,7 +45,6 @@ namespace System.Net.Http.HPack // | 0 | 1 | Index (6+) | // +---+---+-----------------------+ private const byte LiteralHeaderFieldWithIncrementalIndexingMask = 0xc0; - private const byte LiteralHeaderFieldWithIncrementalIndexingRepresentation = 0x40; // http://httpwg.org/specs/rfc7541.html#rfc.section.6.2.2 // 0 1 2 3 4 5 6 7 @@ -53,7 +52,6 @@ namespace System.Net.Http.HPack // | 0 | 0 | 0 | 0 | Index (4+) | // +---+---+-----------------------+ private const byte LiteralHeaderFieldWithoutIndexingMask = 0xf0; - private const byte LiteralHeaderFieldWithoutIndexingRepresentation = 0x00; // http://httpwg.org/specs/rfc7541.html#rfc.section.6.2.3 // 0 1 2 3 4 5 6 7 @@ -61,7 +59,6 @@ namespace System.Net.Http.HPack // | 0 | 0 | 0 | 1 | Index (4+) | // +---+---+-----------------------+ private const byte LiteralHeaderFieldNeverIndexedMask = 0xf0; - private const byte LiteralHeaderFieldNeverIndexedRepresentation = 0x10; // http://httpwg.org/specs/rfc7541.html#rfc.section.6.3 // 0 1 2 3 4 5 6 7 @@ -69,7 +66,6 @@ namespace System.Net.Http.HPack // | 0 | 0 | 1 | Max size (5+) | // +---+---------------------------+ private const byte DynamicTableSizeUpdateMask = 0xe0; - private const byte DynamicTableSizeUpdateRepresentation = 0x20; // http://httpwg.org/specs/rfc7541.html#rfc.section.5.2 // 0 1 2 3 4 5 6 7 @@ -92,6 +88,8 @@ namespace System.Net.Http.HPack private byte[] _stringOctets; private byte[] _headerNameOctets; private byte[] _headerValueOctets; + private (int start, int length)? _headerNameRange; + private (int start, int length)? _headerValueRange; private State _state = State.Ready; private byte[]? _headerName; @@ -124,107 +122,247 @@ namespace System.Net.Http.HPack { foreach (ReadOnlyMemory segment in data) { - DecodeInternal(segment.Span, endHeaders, handler); + DecodeInternal(segment.Span, handler); } CheckIncompleteHeaderBlock(endHeaders); } - public void Decode(ReadOnlySpan data, bool endHeaders, IHttpHeadersHandler? handler) + public void Decode(ReadOnlySpan data, bool endHeaders, IHttpHeadersHandler handler) { - DecodeInternal(data, endHeaders, handler); + DecodeInternal(data, handler); CheckIncompleteHeaderBlock(endHeaders); } - private void DecodeInternal(ReadOnlySpan data, bool endHeaders, IHttpHeadersHandler? handler) + private void DecodeInternal(ReadOnlySpan data, IHttpHeadersHandler handler) { - int intResult; + int currentIndex = 0; - for (int i = 0; i < data.Length; i++) + do { - byte b = data[i]; switch (_state) { case State.Ready: - // TODO: Instead of masking and comparing each prefix value, - // consider doing a 16-way switch on the first four bits (which is the max prefix size). - // Look at this once we have more concrete perf data. - if ((b & IndexedHeaderFieldMask) == IndexedHeaderFieldRepresentation) + Parse(data, ref currentIndex, handler); + break; + case State.HeaderFieldIndex: + ParseHeaderFieldIndex(data, ref currentIndex, handler); + break; + case State.HeaderNameIndex: + ParseHeaderNameIndex(data, ref currentIndex, handler); + break; + case State.HeaderNameLength: + ParseHeaderNameLength(data, ref currentIndex, handler); + break; + case State.HeaderNameLengthContinue: + ParseHeaderNameLengthContinue(data, ref currentIndex, handler); + break; + case State.HeaderName: + ParseHeaderName(data, ref currentIndex, handler); + break; + case State.HeaderValueLength: + ParseHeaderValueLength(data, ref currentIndex, handler); + break; + case State.HeaderValueLengthContinue: + ParseHeaderValueLengthContinue(data, ref currentIndex, handler); + break; + case State.HeaderValue: + ParseHeaderValue(data, ref currentIndex, handler); + break; + case State.DynamicTableSizeUpdate: + ParseDynamicTableSizeUpdate(data, ref currentIndex); + break; + default: + // Can't happen + Debug.Fail("HPACK decoder reach an invalid state"); + throw new NotImplementedException(_state.ToString()); + } + } + // Parse methods each check the length. This check is to see whether there is still data available + // and to continue parsing. + while (currentIndex < data.Length); + + // If a header range was set, but the value was not in the data, then copy the range + // to the name buffer. Must copy because because the data will be replaced and the range + // will no longer be valid. + if (_headerNameRange != null) + { + EnsureStringCapacity(ref _headerNameOctets); + _headerName = _headerNameOctets; + + ReadOnlySpan headerBytes = data.Slice(_headerNameRange.GetValueOrDefault().start, _headerNameRange.GetValueOrDefault().length); + headerBytes.CopyTo(_headerName); + _headerNameLength = headerBytes.Length; + _headerNameRange = null; + } + } + + private void ParseDynamicTableSizeUpdate(ReadOnlySpan data, ref int currentIndex) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + SetDynamicHeaderTableSize(intResult); + _state = State.Ready; + } + } + + private void ParseHeaderValueLength(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (currentIndex < data.Length) + { + byte b = data[currentIndex++]; + + _huffman = IsHuffmanEncoded(b); + + if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out int intResult)) + { + OnStringLength(intResult, nextState: State.HeaderValue); + + if (intResult == 0) + { + OnString(nextState: State.Ready); + ProcessHeaderValue(data, handler); + } + else + { + ParseHeaderValue(data, ref currentIndex, handler); + } + } + else + { + _state = State.HeaderValueLengthContinue; + ParseHeaderValueLengthContinue(data, ref currentIndex, handler); + } + } + } + + private void ParseHeaderNameLengthContinue(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + // IntegerDecoder disallows overlong encodings, where an integer is encoded with more bytes than is strictly required. + // 0 should always be represented by a single byte, so we shouldn't need to check for it in the continuation case. + Debug.Assert(intResult != 0, "A header name length of 0 should never be encoded with a continuation byte."); + + OnStringLength(intResult, nextState: State.HeaderName); + ParseHeaderName(data, ref currentIndex, handler); + } + } + + private void ParseHeaderValueLengthContinue(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + // 0 should always be represented by a single byte, so we shouldn't need to check for it in the continuation case. + Debug.Assert(intResult != 0, "A header value length of 0 should never be encoded with a continuation byte."); + + OnStringLength(intResult, nextState: State.HeaderValue); + ParseHeaderValue(data, ref currentIndex, handler); + } + } + + private void ParseHeaderFieldIndex(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + OnIndexedHeaderField(intResult, handler); + } + } + + private void ParseHeaderNameIndex(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + OnIndexedHeaderName(intResult); + ParseHeaderValueLength(data, ref currentIndex, handler); + } + } + + private void ParseHeaderNameLength(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (currentIndex < data.Length) + { + byte b = data[currentIndex++]; + + _huffman = IsHuffmanEncoded(b); + + if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out int intResult)) + { + if (intResult == 0) + { + throw new HPackDecodingException(SR.Format(SR.net_http_invalid_header_name, "")); + } + + OnStringLength(intResult, nextState: State.HeaderName); + ParseHeaderName(data, ref currentIndex, handler); + } + else + { + _state = State.HeaderNameLengthContinue; + ParseHeaderNameLengthContinue(data, ref currentIndex, handler); + } + } + } + + private void Parse(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (currentIndex < data.Length) + { + Debug.Assert(_state == State.Ready, "Should be ready to parse a new header."); + + byte b = data[currentIndex++]; + + switch (BitOperations.LeadingZeroCount(b) - 24) // byte 'b' is extended to uint, so will have 24 extra 0s. + { + case 0: // Indexed Header Field { _headersObserved = true; int val = b & ~IndexedHeaderFieldMask; - if (_integerDecoder.BeginTryDecode((byte)val, IndexedHeaderFieldPrefix, out intResult)) + if (_integerDecoder.BeginTryDecode((byte)val, IndexedHeaderFieldPrefix, out int intResult)) { OnIndexedHeaderField(intResult, handler); } else { _state = State.HeaderFieldIndex; + ParseHeaderFieldIndex(data, ref currentIndex, handler); } + break; } - else if ((b & LiteralHeaderFieldWithIncrementalIndexingMask) == LiteralHeaderFieldWithIncrementalIndexingRepresentation) - { - _headersObserved = true; - - _index = true; - int val = b & ~LiteralHeaderFieldWithIncrementalIndexingMask; - - if (val == 0) - { - _state = State.HeaderNameLength; - } - else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldWithIncrementalIndexingPrefix, out intResult)) - { - OnIndexedHeaderName(intResult); - } - else - { - _state = State.HeaderNameIndex; - } - } - else if ((b & LiteralHeaderFieldWithoutIndexingMask) == LiteralHeaderFieldWithoutIndexingRepresentation) - { - _headersObserved = true; - - _index = false; - int val = b & ~LiteralHeaderFieldWithoutIndexingMask; - - if (val == 0) - { - _state = State.HeaderNameLength; - } - else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldWithoutIndexingPrefix, out intResult)) - { - OnIndexedHeaderName(intResult); - } - else - { - _state = State.HeaderNameIndex; - } - } - else if ((b & LiteralHeaderFieldNeverIndexedMask) == LiteralHeaderFieldNeverIndexedRepresentation) - { - _headersObserved = true; - - _index = false; - int val = b & ~LiteralHeaderFieldNeverIndexedMask; - - if (val == 0) - { - _state = State.HeaderNameLength; - } - else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldNeverIndexedPrefix, out intResult)) - { - OnIndexedHeaderName(intResult); - } - else - { - _state = State.HeaderNameIndex; - } - } - else if ((b & DynamicTableSizeUpdateMask) == DynamicTableSizeUpdateRepresentation) + case 1: // Literal Header Field with Incremental Indexing + ParseLiteralHeaderField( + data, + ref currentIndex, + b, + LiteralHeaderFieldWithIncrementalIndexingMask, + LiteralHeaderFieldWithIncrementalIndexingPrefix, + index: true, + handler); + break; + case 4: + default: // Literal Header Field without Indexing + ParseLiteralHeaderField( + data, + ref currentIndex, + b, + LiteralHeaderFieldWithoutIndexingMask, + LiteralHeaderFieldWithoutIndexingPrefix, + index: false, + handler); + break; + case 3: // Literal Header Field Never Indexed + ParseLiteralHeaderField( + data, + ref currentIndex, + b, + LiteralHeaderFieldNeverIndexedMask, + LiteralHeaderFieldNeverIndexedPrefix, + index: false, + handler); + break; + case 2: // Dynamic Table Size Update { // https://tools.ietf.org/html/rfc7541#section-4.2 // This dynamic table size @@ -235,125 +373,107 @@ namespace System.Net.Http.HPack throw new HPackDecodingException(SR.net_http_hpack_late_dynamic_table_size_update); } - if (_integerDecoder.BeginTryDecode((byte)(b & ~DynamicTableSizeUpdateMask), DynamicTableSizeUpdatePrefix, out intResult)) + if (_integerDecoder.BeginTryDecode((byte)(b & ~DynamicTableSizeUpdateMask), DynamicTableSizeUpdatePrefix, out int intResult)) { SetDynamicHeaderTableSize(intResult); } else { _state = State.DynamicTableSizeUpdate; + ParseDynamicTableSizeUpdate(data, ref currentIndex); } + break; } - else - { - // Can't happen - Debug.Fail("Unreachable code"); - throw new InvalidOperationException("Unreachable code."); - } + } + } + } - break; - case State.HeaderFieldIndex: - if (_integerDecoder.TryDecode(b, out intResult)) - { - OnIndexedHeaderField(intResult, handler); - } + private void ParseLiteralHeaderField(ReadOnlySpan data, ref int currentIndex, byte b, byte mask, byte indexPrefix, bool index, IHttpHeadersHandler handler) + { + _headersObserved = true; - break; - case State.HeaderNameIndex: - if (_integerDecoder.TryDecode(b, out intResult)) - { - OnIndexedHeaderName(intResult); - } + _index = index; + int val = b & ~mask; - break; - case State.HeaderNameLength: - _huffman = (b & HuffmanMask) != 0; + if (val == 0) + { + _state = State.HeaderNameLength; + ParseHeaderNameLength(data, ref currentIndex, handler); + } + else + { + if (_integerDecoder.BeginTryDecode((byte)val, indexPrefix, out int intResult)) + { + OnIndexedHeaderName(intResult); + ParseHeaderValueLength(data, ref currentIndex, handler); + } + else + { + _state = State.HeaderNameIndex; + ParseHeaderNameIndex(data, ref currentIndex, handler); + } + } + } - if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out intResult)) - { - if (intResult == 0) - { - throw new HPackDecodingException(SR.Format(SR.net_http_invalid_header_name, "")); - } + private void ParseHeaderName(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + // Read remaining chars, up to the length of the current data + int count = Math.Min(_stringLength - _stringIndex, data.Length - currentIndex); - OnStringLength(intResult, nextState: State.HeaderName); - } - else - { - _state = State.HeaderNameLengthContinue; - } + // Check whether the whole string is available in the data and no decompression required. + // If string is good then mark its range. + // NOTE: it may need to be copied to buffer later the if value is not current data. + if (count == _stringLength && !_huffman) + { + // Fast path. Store the range rather than copying. + _headerNameRange = (start: currentIndex, count); + currentIndex += count; - break; - case State.HeaderNameLengthContinue: - if (_integerDecoder.TryDecode(b, out intResult)) - { - // IntegerDecoder disallows overlong encodings, where an integer is encoded with more bytes than is strictly required. - // 0 should always be represented by a single byte, so we shouldn't need to check for it in the continuation case. - Debug.Assert(intResult != 0, "A header name length of 0 should never be encoded with a continuation byte."); + _state = State.HeaderValueLength; + } + else + { + // Copy string to temporary buffer. + // _stringOctets was already + data.Slice(currentIndex, count).CopyTo(_stringOctets.AsSpan(_stringIndex)); + _stringIndex += count; + currentIndex += count; - OnStringLength(intResult, nextState: State.HeaderName); - } + if (_stringIndex == _stringLength) + { + OnString(nextState: State.HeaderValueLength); + ParseHeaderValueLength(data, ref currentIndex, handler); + } + } + } - break; - case State.HeaderName: - _stringOctets[_stringIndex++] = b; + private void ParseHeaderValue(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + // Read remaining chars, up to the length of the current data + int count = Math.Min(_stringLength - _stringIndex, data.Length - currentIndex); - if (_stringIndex == _stringLength) - { - OnString(nextState: State.HeaderValueLength); - } + // Check whether the whole string is available in the data and no decompressed required. + // If string is good then mark its range. + if (count == _stringLength && !_huffman) + { + // Fast path. Store the range rather than copying. + _headerValueRange = (start: currentIndex, count); + currentIndex += count; - break; - case State.HeaderValueLength: - _huffman = (b & HuffmanMask) != 0; + _state = State.Ready; + ProcessHeaderValue(data, handler); + } + else + { + // Copy string to temporary buffer. + data.Slice(currentIndex, count).CopyTo(_stringOctets.AsSpan(_stringIndex)); + _stringIndex += count; + currentIndex += count; - if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out intResult)) - { - OnStringLength(intResult, nextState: State.HeaderValue); - - if (intResult == 0) - { - ProcessHeaderValue(handler); - } - } - else - { - _state = State.HeaderValueLengthContinue; - } - - break; - case State.HeaderValueLengthContinue: - if (_integerDecoder.TryDecode(b, out intResult)) - { - // IntegerDecoder disallows overlong encodings where an integer is encoded with more bytes than is strictly required. - // 0 should always be represented by a single byte, so we shouldn't need to check for it in the continuation case. - Debug.Assert(intResult != 0, "A header value length of 0 should never be encoded with a continuation byte."); - - OnStringLength(intResult, nextState: State.HeaderValue); - } - - break; - case State.HeaderValue: - _stringOctets[_stringIndex++] = b; - - if (_stringIndex == _stringLength) - { - ProcessHeaderValue(handler); - } - - break; - case State.DynamicTableSizeUpdate: - if (_integerDecoder.TryDecode(b, out intResult)) - { - SetDynamicHeaderTableSize(intResult); - _state = State.Ready; - } - - break; - default: - // Can't happen - Debug.Fail("HPACK decoder reach an invalid state"); - throw new NotImplementedException(_state.ToString()); + if (_stringIndex == _stringLength) + { + OnString(nextState: State.Ready); + ProcessHeaderValue(data, handler); } } } @@ -371,14 +491,20 @@ namespace System.Net.Http.HPack } } - private void ProcessHeaderValue(IHttpHeadersHandler? handler) + private void ProcessHeaderValue(ReadOnlySpan data, IHttpHeadersHandler handler) { - OnString(nextState: State.Ready); + ReadOnlySpan headerNameSpan = _headerNameRange == null + ? new Span(_headerName, 0, _headerNameLength) + : data.Slice(_headerNameRange.GetValueOrDefault().start, _headerNameRange.GetValueOrDefault().length); - var headerNameSpan = new Span(_headerName, 0, _headerNameLength); - var headerValueSpan = new Span(_headerValueOctets, 0, _headerValueLength); + ReadOnlySpan headerValueSpan = _headerValueRange == null + ? new Span(_headerValueOctets, 0, _headerValueLength) + : data.Slice(_headerValueRange.GetValueOrDefault().start, _headerValueRange.GetValueOrDefault().length); - handler?.OnHeader(headerNameSpan, headerValueSpan); + handler.OnHeader(headerNameSpan, headerValueSpan); + + _headerNameRange = null; + _headerValueRange = null; if (_index) { @@ -395,18 +521,17 @@ namespace System.Net.Http.HPack } } - private void OnIndexedHeaderField(int index, IHttpHeadersHandler? handler) + private void OnIndexedHeaderField(int index, IHttpHeadersHandler handler) { - HeaderField header = GetHeader(index); - handler?.OnHeader(header.Name, header.Value); + ref readonly HeaderField header = ref GetHeader(index); + handler.OnHeader(header.Name, header.Value); _state = State.Ready; } private void OnIndexedHeaderName(int index) { - HeaderField header = GetHeader(index); - _headerName = header.Name; - _headerNameLength = header.Name.Length; + _headerName = GetHeader(index).Name; + _headerNameLength = _headerName.Length; _state = State.HeaderValueLength; } @@ -437,11 +562,7 @@ namespace System.Net.Http.HPack } else { - if (dst.Length < _stringLength) - { - dst = new byte[Math.Max(_stringLength, dst.Length * 2)]; - } - + EnsureStringCapacity(ref dst); Buffer.BlockCopy(_stringOctets, 0, dst, 0, _stringLength); return _stringLength; } @@ -467,13 +588,41 @@ namespace System.Net.Http.HPack _state = nextState; } - private HeaderField GetHeader(int index) + private void EnsureStringCapacity(ref byte[] dst) + { + if (dst.Length < _stringLength) + { + dst = new byte[Math.Max(_stringLength, dst.Length * 2)]; + } + } + + private bool TryDecodeInteger(ReadOnlySpan data, ref int currentIndex, out int result) + { + for (; currentIndex < data.Length; currentIndex++) + { + if (_integerDecoder.TryDecode(data[currentIndex], out result)) + { + currentIndex++; + return true; + } + } + + result = default; + return false; + } + + private static bool IsHuffmanEncoded(byte b) + { + return (b & HuffmanMask) != 0; + } + + private ref readonly HeaderField GetHeader(int index) { try { - return index <= H2StaticTable.Count - ? H2StaticTable.Get(index - 1) - : _dynamicTable[index - H2StaticTable.Count - 1]; + return ref index <= H2StaticTable.Count + ? ref H2StaticTable.Get(index - 1) + : ref _dynamicTable[index - H2StaticTable.Count - 1]; } catch (IndexOutOfRangeException) { diff --git a/src/Shared/runtime/Http2/Hpack/HPackEncoder.cs b/src/Shared/runtime/Http2/Hpack/HPackEncoder.cs index 97cdea1c50..4a8511e682 100644 --- a/src/Shared/runtime/Http2/Hpack/HPackEncoder.cs +++ b/src/Shared/runtime/Http2/Hpack/HPackEncoder.cs @@ -54,7 +54,7 @@ namespace System.Net.Http.HPack case 404: case 500: // Status codes which exist in the HTTP/2 StaticTable. - return EncodeIndexedHeaderField(H2StaticTable.StatusIndex[statusCode], destination, out bytesWritten); + return EncodeIndexedHeaderField(H2StaticTable.GetStatusIndex(statusCode), destination, out bytesWritten); default: // If the status code doesn't have a static index then we need to include the full value. // Write a status index and then the number bytes as a string literal. diff --git a/src/Shared/test/Shared.Tests/runtime/Http2/HPackDecoderTest.cs b/src/Shared/test/Shared.Tests/runtime/Http2/HPackDecoderTest.cs index 2afdb29901..d5d26ccb37 100644 --- a/src/Shared/test/Shared.Tests/runtime/Http2/HPackDecoderTest.cs +++ b/src/Shared/test/Shared.Tests/runtime/Http2/HPackDecoderTest.cs @@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; namespace System.Net.Http.Unit.Tests.HPack { - public class HPackDecoderTests : IHttpHeadersHandler + public class HPackDecoderTests { private const int DynamicTableInitialMaxSize = 4096; private const int MaxHeaderFieldSize = 8192; @@ -89,42 +89,26 @@ namespace System.Net.Http.Unit.Tests.HPack private readonly DynamicTable _dynamicTable; private readonly HPackDecoder _decoder; - - private readonly Dictionary _decodedHeaders = new Dictionary(); + private readonly TestHttpHeadersHandler _handler = new TestHttpHeadersHandler(); public HPackDecoderTests() { - _dynamicTable = new DynamicTable(DynamicTableInitialMaxSize); - _decoder = new HPackDecoder(DynamicTableInitialMaxSize, MaxHeaderFieldSize, _dynamicTable); + (_dynamicTable, _decoder) = CreateDecoderAndTable(); } - void IHttpHeadersHandler.OnHeader(ReadOnlySpan name, ReadOnlySpan value) + private static (DynamicTable, HPackDecoder) CreateDecoderAndTable() { - string headerName = Encoding.ASCII.GetString(name); - string headerValue = Encoding.ASCII.GetString(value); + var dynamicTable = new DynamicTable(DynamicTableInitialMaxSize); + var decoder = new HPackDecoder(DynamicTableInitialMaxSize, MaxHeaderFieldSize, dynamicTable); - _decodedHeaders[headerName] = headerValue; + return (dynamicTable, decoder); } - void IHttpHeadersHandler.OnStaticIndexedHeader(int index) - { - // Not yet implemented for HPACK. - throw new NotImplementedException(); - } - - void IHttpHeadersHandler.OnStaticIndexedHeader(int index, ReadOnlySpan value) - { - // Not yet implemented for HPACK. - throw new NotImplementedException(); - } - - void IHttpHeadersHandler.OnHeadersComplete(bool endStream) { } - [Fact] public void DecodesIndexedHeaderField_StaticTable() { - _decoder.Decode(_indexedHeaderStatic, endHeaders: true, handler: this); - Assert.Equal("GET", _decodedHeaders[":method"]); + _decoder.Decode(_indexedHeaderStatic, endHeaders: true, handler: _handler); + Assert.Equal("GET", _handler.DecodedHeaders[":method"]); } [Fact] @@ -134,17 +118,17 @@ namespace System.Net.Http.Unit.Tests.HPack _dynamicTable.Insert(_headerNameBytes, _headerValueBytes); // Index it - _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: this); - Assert.Equal(_headerValueString, _decodedHeaders[_headerNameString]); + _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: _handler); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_headerNameString]); } [Fact] public void DecodesIndexedHeaderField_OutOfRange_Error() { HPackDecodingException exception = Assert.Throws(() => - _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: this)); + _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_invalid_index, 62), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -218,9 +202,9 @@ namespace System.Net.Http.Unit.Tests.HPack // 11 1110 (Indexed Name - Index 62 encoded with 6-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) // Index 62 is the first entry in the dynamic table. If there's nothing there, the decoder should throw. - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x7e }, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x7e }, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_invalid_index, 62), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -294,9 +278,9 @@ namespace System.Net.Http.Unit.Tests.HPack // 1111 0010 1111 (Indexed Name - Index 62 encoded with 4-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) // Index 62 is the first entry in the dynamic table. If there's nothing there, the decoder should throw. - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x0f, 0x2f }, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x0f, 0x2f }, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_invalid_index, 62), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -310,6 +294,19 @@ namespace System.Net.Http.Unit.Tests.HPack TestDecodeWithoutIndexing(encoded, _headerNameString, _headerValueString); } + [Fact] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_Duplicated() + { + byte[] encoded = _literalHeaderFieldNeverIndexedNewName + .Concat(_headerName) + .Concat(_headerValue) + .ToArray(); + + encoded = encoded.Concat(encoded).ToArray(); + + TestDecodeWithoutIndexing(encoded, _headerNameString, _headerValueString); + } + [Fact] public void DecodesLiteralHeaderFieldNeverIndexed_NewName_HuffmanEncodedName() { @@ -376,9 +373,9 @@ namespace System.Net.Http.Unit.Tests.HPack // 1111 0010 1111 (Indexed Name - Index 62 encoded with 4-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) // Index 62 is the first entry in the dynamic table. If there's nothing there, the decoder should throw. - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x1f, 0x2f }, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x1f, 0x2f }, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_invalid_index, 62), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -389,10 +386,10 @@ namespace System.Net.Http.Unit.Tests.HPack Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); - _decoder.Decode(new byte[] { 0x3e }, endHeaders: true, handler: this); + _decoder.Decode(new byte[] { 0x3e }, endHeaders: true, handler: _handler); Assert.Equal(30, _dynamicTable.MaxSize); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -404,7 +401,7 @@ namespace System.Net.Http.Unit.Tests.HPack Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); byte[] data = _indexedHeaderStatic.Concat(new byte[] { 0x3e }).ToArray(); - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(data, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(data, endHeaders: true, handler: _handler)); Assert.Equal(SR.net_http_hpack_late_dynamic_table_size_update, exception.Message); } @@ -413,13 +410,13 @@ namespace System.Net.Http.Unit.Tests.HPack { Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); - _decoder.Decode(_indexedHeaderStatic, endHeaders: false, handler: this); - Assert.Equal("GET", _decodedHeaders[":method"]); + _decoder.Decode(_indexedHeaderStatic, endHeaders: false, handler: _handler); + Assert.Equal("GET", _handler.DecodedHeaders[":method"]); // 001 (Dynamic Table Size Update) // 11110 (30 encoded with 5-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) byte[] data = new byte[] { 0x3e }; - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(data, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(data, endHeaders: true, handler: _handler)); Assert.Equal(SR.net_http_hpack_late_dynamic_table_size_update, exception.Message); } @@ -428,12 +425,12 @@ namespace System.Net.Http.Unit.Tests.HPack { Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); - _decoder.Decode(_indexedHeaderStatic, endHeaders: true, handler: this); - Assert.Equal("GET", _decodedHeaders[":method"]); + _decoder.Decode(_indexedHeaderStatic, endHeaders: true, handler: _handler); + Assert.Equal("GET", _handler.DecodedHeaders[":method"]); // 001 (Dynamic Table Size Update) // 11110 (30 encoded with 5-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) - _decoder.Decode(new byte[] { 0x3e }, endHeaders: true, handler: this); + _decoder.Decode(new byte[] { 0x3e }, endHeaders: true, handler: _handler); Assert.Equal(30, _dynamicTable.MaxSize); } @@ -447,9 +444,9 @@ namespace System.Net.Http.Unit.Tests.HPack Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); HPackDecodingException exception = Assert.Throws(() => - _decoder.Decode(new byte[] { 0x3f, 0xe2, 0x1f }, endHeaders: true, handler: this)); + _decoder.Decode(new byte[] { 0x3f, 0xe2, 0x1f }, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_large_table_size_update, 4097, DynamicTableInitialMaxSize), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -459,9 +456,9 @@ namespace System.Net.Http.Unit.Tests.HPack .Concat(new byte[] { 0xff, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix .ToArray(); - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_headers_exceeded_length, MaxHeaderFieldSize), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -477,9 +474,57 @@ namespace System.Net.Http.Unit.Tests.HPack .Concat(Encoding.ASCII.GetBytes(string8193)) .ToArray(); - decoder.Decode(encoded, endHeaders: true, handler: this); + decoder.Decode(encoded, endHeaders: true, handler: _handler); - Assert.Equal(string8193, _decodedHeaders[string8193]); + Assert.Equal(string8193, _handler.DecodedHeaders[string8193]); + } + + [Fact] + public void DecodesStringLength_IndividualBytes() + { + HPackDecoder decoder = new HPackDecoder(DynamicTableInitialMaxSize, MaxHeaderFieldSize + 1); + string string8193 = new string('a', MaxHeaderFieldSize + 1); + + byte[] encoded = _literalHeaderFieldWithoutIndexingNewName + .Concat(new byte[] { 0x7f, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix, no Huffman encoding + .Concat(Encoding.ASCII.GetBytes(string8193)) + .Concat(new byte[] { 0x7f, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix, no Huffman encoding + .Concat(Encoding.ASCII.GetBytes(string8193)) + .ToArray(); + + for (int i = 0; i < encoded.Length; i++) + { + bool end = i + 1 == encoded.Length; + + decoder.Decode(new byte[] { encoded[i] }, endHeaders: end, handler: _handler); + } + + Assert.Equal(string8193, _handler.DecodedHeaders[string8193]); + } + + [Fact] + public void DecodesHeaderNameAndValue_SeparateSegments() + { + HPackDecoder decoder = new HPackDecoder(DynamicTableInitialMaxSize, MaxHeaderFieldSize + 1); + string string8193 = new string('a', MaxHeaderFieldSize + 1); + + byte[][] segments = new byte[][] + { + _literalHeaderFieldWithoutIndexingNewName, + new byte[] { 0x7f, 0x82, 0x3f }, // 8193 encoded with 7-bit prefix, no Huffman encoding + Encoding.ASCII.GetBytes(string8193), + new byte[] { 0x7f, 0x82, 0x3f }, // 8193 encoded with 7-bit prefix, no Huffman encoding + Encoding.ASCII.GetBytes(string8193) + }; + + for (int i = 0; i < segments.Length; i++) + { + bool end = i + 1 == segments.Length; + + decoder.Decode(segments[i], endHeaders: end, handler: _handler); + } + + Assert.Equal(string8193, _handler.DecodedHeaders[string8193]); } public static readonly TheoryData _incompleteHeaderBlockData = new TheoryData @@ -567,9 +612,9 @@ namespace System.Net.Http.Unit.Tests.HPack [MemberData(nameof(_incompleteHeaderBlockData))] public void DecodesIncompleteHeaderBlock_Error(byte[] encoded) { - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: _handler)); Assert.Equal(SR.net_http_hpack_incomplete_header_block, exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } public static readonly TheoryData _huffmanDecodingErrorData = new TheoryData @@ -601,43 +646,89 @@ namespace System.Net.Http.Unit.Tests.HPack [MemberData(nameof(_huffmanDecodingErrorData))] public void WrapsHuffmanDecodingExceptionInHPackDecodingException(byte[] encoded) { - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: _handler)); Assert.Equal(SR.net_http_hpack_huffman_decode_failed, exception.Message); Assert.IsType(exception.InnerException); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } - private void TestDecodeWithIndexing(byte[] encoded, string expectedHeaderName, string expectedHeaderValue) + private static void TestDecodeWithIndexing(byte[] encoded, string expectedHeaderName, string expectedHeaderValue) { - TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: true); + TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: true, byteAtATime: false); + TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: true, byteAtATime: true); } - private void TestDecodeWithoutIndexing(byte[] encoded, string expectedHeaderName, string expectedHeaderValue) + private static void TestDecodeWithoutIndexing(byte[] encoded, string expectedHeaderName, string expectedHeaderValue) { - TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: false); + TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: false, byteAtATime: false); + TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: false, byteAtATime: true); } - private void TestDecode(byte[] encoded, string expectedHeaderName, string expectedHeaderValue, bool expectDynamicTableEntry) + private static void TestDecode(byte[] encoded, string expectedHeaderName, string expectedHeaderValue, bool expectDynamicTableEntry, bool byteAtATime) { - Assert.Equal(0, _dynamicTable.Count); - Assert.Equal(0, _dynamicTable.Size); + var (dynamicTable, decoder) = CreateDecoderAndTable(); + var handler = new TestHttpHeadersHandler(); - _decoder.Decode(encoded, endHeaders: true, handler: this); + Assert.Equal(0, dynamicTable.Count); + Assert.Equal(0, dynamicTable.Size); - Assert.Equal(expectedHeaderValue, _decodedHeaders[expectedHeaderName]); - - if (expectDynamicTableEntry) + if (!byteAtATime) { - Assert.Equal(1, _dynamicTable.Count); - Assert.Equal(expectedHeaderName, Encoding.ASCII.GetString(_dynamicTable[0].Name)); - Assert.Equal(expectedHeaderValue, Encoding.ASCII.GetString(_dynamicTable[0].Value)); - Assert.Equal(expectedHeaderName.Length + expectedHeaderValue.Length + 32, _dynamicTable.Size); + decoder.Decode(encoded, endHeaders: true, handler: handler); } else { - Assert.Equal(0, _dynamicTable.Count); - Assert.Equal(0, _dynamicTable.Size); + // Parse data in 1 byte chunks, separated by empty chunks + for (int i = 0; i < encoded.Length; i++) + { + bool end = i + 1 == encoded.Length; + + decoder.Decode(Array.Empty(), endHeaders: false, handler: handler); + decoder.Decode(new byte[] { encoded[i] }, endHeaders: end, handler: handler); + } + } + + Assert.Equal(expectedHeaderValue, handler.DecodedHeaders[expectedHeaderName]); + + if (expectDynamicTableEntry) + { + Assert.Equal(1, dynamicTable.Count); + Assert.Equal(expectedHeaderName, Encoding.ASCII.GetString(dynamicTable[0].Name)); + Assert.Equal(expectedHeaderValue, Encoding.ASCII.GetString(dynamicTable[0].Value)); + Assert.Equal(expectedHeaderName.Length + expectedHeaderValue.Length + 32, dynamicTable.Size); + } + else + { + Assert.Equal(0, dynamicTable.Count); + Assert.Equal(0, dynamicTable.Size); } } } + + public class TestHttpHeadersHandler : IHttpHeadersHandler + { + public Dictionary DecodedHeaders { get; } = new Dictionary(); + + void IHttpHeadersHandler.OnHeader(ReadOnlySpan name, ReadOnlySpan value) + { + string headerName = Encoding.ASCII.GetString(name); + string headerValue = Encoding.ASCII.GetString(value); + + DecodedHeaders[headerName] = headerValue; + } + + void IHttpHeadersHandler.OnStaticIndexedHeader(int index) + { + // Not yet implemented for HPACK. + throw new NotImplementedException(); + } + + void IHttpHeadersHandler.OnStaticIndexedHeader(int index, ReadOnlySpan value) + { + // Not yet implemented for HPACK. + throw new NotImplementedException(); + } + + void IHttpHeadersHandler.OnHeadersComplete(bool endStream) { } + } } From 210a31df35f60314a4b28312ea1f4dc0f4e81b78 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2020 21:44:00 +0000 Subject: [PATCH 005/100] [master] Update dependencies from dotnet/efcore (#23230) * Update dependencies from https://github.com/dotnet/efcore build 20200622.4 Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.7.20322.3 -> To Version 5.0.0-preview.7.20322.4 * Update dependencies from https://github.com/dotnet/efcore build 20200622.6 Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.7.20322.3 -> To Version 5.0.0-preview.8.20322.6 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index cc30482c95..79ac930ee6 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 7c209eaef1b2bd6b502896c618b5ffe57d34c559 + 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 - + https://github.com/dotnet/efcore - 7c209eaef1b2bd6b502896c618b5ffe57d34c559 + 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 - + https://github.com/dotnet/efcore - 7c209eaef1b2bd6b502896c618b5ffe57d34c559 + 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 - + https://github.com/dotnet/efcore - 7c209eaef1b2bd6b502896c618b5ffe57d34c559 + 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 - + https://github.com/dotnet/efcore - 7c209eaef1b2bd6b502896c618b5ffe57d34c559 + 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 - + https://github.com/dotnet/efcore - 7c209eaef1b2bd6b502896c618b5ffe57d34c559 + 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 - + https://github.com/dotnet/efcore - 7c209eaef1b2bd6b502896c618b5ffe57d34c559 + 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index cd52d9be9e..ade65c346e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.7.20322.3 - 5.0.0-preview.7.20322.3 - 5.0.0-preview.7.20322.3 - 5.0.0-preview.7.20322.3 - 5.0.0-preview.7.20322.3 - 5.0.0-preview.7.20322.3 - 5.0.0-preview.7.20322.3 + 5.0.0-preview.8.20322.6 + 5.0.0-preview.8.20322.6 + 5.0.0-preview.8.20322.6 + 5.0.0-preview.8.20322.6 + 5.0.0-preview.8.20322.6 + 5.0.0-preview.8.20322.6 + 5.0.0-preview.8.20322.6 From 26cc3b43a2f5723e171dc9ebc828420147da76b1 Mon Sep 17 00:00:00 2001 From: Tanay Parikh Date: Mon, 22 Jun 2020 17:54:52 -0700 Subject: [PATCH 010/100] Unquarantine Tests (#23098) Found a bunch of tests running for 30+ days with 100% pass rate. --- .../test/Rendering/RendererSynchronizationContextTest.cs | 3 +-- .../Specification.Tests/src/UserManagerSpecificationTests.cs | 3 --- src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs | 1 - .../test/Common.FunctionalTests/ClientCertificateTests.cs | 1 - .../InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs | 3 --- .../test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs | 2 -- .../Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs | 1 - .../InMemory.FunctionalTests/RequestHeaderLimitsTests.cs | 1 - .../Kestrel/test/InMemory.FunctionalTests/RequestTests.cs | 1 - .../csharp/Client/test/UnitTests/TimerAwaitableTests.cs | 1 - src/Tools/dotnet-watch/test/AppWithDepsTests.cs | 1 - src/Tools/dotnet-watch/test/DotNetWatcherTests.cs | 2 -- src/Tools/dotnet-watch/test/GlobbingAppTests.cs | 5 ----- src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs | 1 - src/Tools/dotnet-watch/test/NoDepsAppTests.cs | 2 -- src/Tools/dotnet-watch/test/ProgramTests.cs | 1 - 16 files changed, 1 insertion(+), 28 deletions(-) diff --git a/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs b/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs index 77544baa77..b8908caff8 100644 --- a/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs +++ b/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Components.Rendering Thread capturedThread = null; var e = new ManualResetEventSlim(); - + // Act context.Post((_) => { @@ -766,7 +766,6 @@ namespace Microsoft.AspNetCore.Components.Rendering } [Fact] - [QuarantinedTest] public async Task InvokeAsync_SyncWorkInAsyncTaskIsCompletedFirst() { // Simplified version of ServerComponentRenderingTest.CanDispatchAsyncWorkToSyncContext diff --git a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs index 4bc1a37559..f675482bfb 100644 --- a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs +++ b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs @@ -1450,7 +1450,6 @@ namespace Microsoft.AspNetCore.Identity.Test /// /// Task [Fact] - [QuarantinedTest] public async Task ChangePhoneNumberFailsWithWrongPhoneNumber() { var manager = CreateManager(); @@ -1471,7 +1470,6 @@ namespace Microsoft.AspNetCore.Identity.Test /// /// Task [Fact] - [QuarantinedTest] public async Task CanVerifyPhoneNumber() { var manager = CreateManager(); @@ -1519,7 +1517,6 @@ namespace Microsoft.AspNetCore.Identity.Test /// /// Task [Fact] - [QuarantinedTest] public async Task CanChangeEmailOnlyIfEmailSame() { var manager = CreateManager(); diff --git a/src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs b/src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs index 90313c0efa..525f1107f2 100644 --- a/src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs +++ b/src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs @@ -887,7 +887,6 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers } [Fact] - [QuarantinedTest] public async Task ProcessAsync_AwaitersUseTheResultOfExecutor() { // Arrange diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/ClientCertificateTests.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/ClientCertificateTests.cs index d61c6fa5da..f883d88f83 100644 --- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/ClientCertificateTests.cs +++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/ClientCertificateTests.cs @@ -34,7 +34,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests .WithAllHostingModels(); [ConditionalTheory] - [QuarantinedTest] [MemberData(nameof(TestVariants))] [MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win8)] public Task HttpsNoClientCert_NoClientCert(TestVariant variant) diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs index 43a3f9d7a2..a1cf418fe3 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs @@ -300,7 +300,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - [QuarantinedTest] public async Task StreamPool_MultipleStreamsInSequence_PooledStreamReused() { TaskCompletionSource appDelegateTcs = null; @@ -365,7 +364,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - [QuarantinedTest] public async Task StreamPool_StreamIsInvalidState_DontReturnedToPool() { var serverTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -4010,7 +4008,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests [Theory] [InlineData(true)] [InlineData(false)] - [QuarantinedTest] public async Task CONTINUATION_Received_WithTrailers_Available(bool sendData) { await InitializeConnectionAsync(_readTrailersApplication); diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs index 99bbd21ea5..c433bb90be 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs @@ -371,7 +371,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - [QuarantinedTest] public async Task DATA_Sent_TooSlowlyDueToFlowControlOnSmallWrite_AbortsConnectionAfterGracePeriod() { var mockSystemClock = _serviceContext.MockSystemClock; @@ -426,7 +425,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - [QuarantinedTest] public async Task DATA_Sent_TooSlowlyDueToOutputFlowControlOnLargeWrite_AbortsConnectionAfterRateTimeout() { var mockSystemClock = _serviceContext.MockSystemClock; diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs index 4849965c40..e36759544c 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs @@ -220,7 +220,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests [Fact] [Repeat(20)] - [QuarantinedTest] public async Task DoesNotThrowObjectDisposedExceptionFromWriteAsyncAfterConnectionIsAborted() { var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestHeaderLimitsTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestHeaderLimitsTests.cs index c5002a8c8c..5ab5b467e8 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestHeaderLimitsTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestHeaderLimitsTests.cs @@ -23,7 +23,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests [InlineData(5, 0)] [InlineData(5, 1)] [InlineData(5, 1337)] - [QuarantinedTest] public async Task ServerAcceptsRequestWithHeaderTotalSizeWithinLimit(int headerCount, int extraLimit) { var headers = MakeHeaders(headerCount); diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs index 3ada9a09a6..0d1c028fe5 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs @@ -559,7 +559,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests } [Fact] - [QuarantinedTest] public async Task TraceIdentifierIsUnique() { const int identifierLength = 22; diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/TimerAwaitableTests.cs b/src/SignalR/clients/csharp/Client/test/UnitTests/TimerAwaitableTests.cs index e0e7248df4..869626d7cd 100644 --- a/src/SignalR/clients/csharp/Client/test/UnitTests/TimerAwaitableTests.cs +++ b/src/SignalR/clients/csharp/Client/test/UnitTests/TimerAwaitableTests.cs @@ -13,7 +13,6 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public class TimerAwaitableTests { [Fact] - [QuarantinedTest] public async Task FinalizerRunsIfTimerAwaitableReferencesObject() { var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/Tools/dotnet-watch/test/AppWithDepsTests.cs b/src/Tools/dotnet-watch/test/AppWithDepsTests.cs index 5954f540b5..c74e24a6c5 100644 --- a/src/Tools/dotnet-watch/test/AppWithDepsTests.cs +++ b/src/Tools/dotnet-watch/test/AppWithDepsTests.cs @@ -20,7 +20,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task ChangeFileInDependency() { await _app.StartWatcherAsync(); diff --git a/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs b/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs index d07f4e25a4..f085a358ae 100644 --- a/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs +++ b/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs @@ -23,7 +23,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RunsWithDotnetWatchEnvVariable() { Assert.True(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_WATCH")), "DOTNET_WATCH cannot be set already when this test is running"); @@ -36,7 +35,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RunsWithIterationEnvVariable() { await _app.StartWatcherAsync(); diff --git a/src/Tools/dotnet-watch/test/GlobbingAppTests.cs b/src/Tools/dotnet-watch/test/GlobbingAppTests.cs index 9383b2d728..8ec696e1fe 100644 --- a/src/Tools/dotnet-watch/test/GlobbingAppTests.cs +++ b/src/Tools/dotnet-watch/test/GlobbingAppTests.cs @@ -24,7 +24,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Theory] [InlineData(true)] [InlineData(false)] - [QuarantinedTest] public async Task ChangeCompiledFile(bool usePollingWatcher) { _app.UsePollingWatcher = usePollingWatcher; @@ -43,7 +42,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task DeleteCompiledFile() { await _app.StartWatcherAsync(); @@ -60,7 +58,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task DeleteSourceFolder() { await _app.StartWatcherAsync(); @@ -77,7 +74,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RenameCompiledFile() { await _app.StartWatcherAsync(); @@ -90,7 +86,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task ChangeExcludedFile() { await _app.StartWatcherAsync(); diff --git a/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs b/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs index 4c5907dda6..d3aee43cac 100644 --- a/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs +++ b/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs @@ -77,7 +77,6 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests } [Fact] - [QuarantinedTest] public async Task SingleTfm() { _tempDir diff --git a/src/Tools/dotnet-watch/test/NoDepsAppTests.cs b/src/Tools/dotnet-watch/test/NoDepsAppTests.cs index b7171d5ad2..6b943e262c 100644 --- a/src/Tools/dotnet-watch/test/NoDepsAppTests.cs +++ b/src/Tools/dotnet-watch/test/NoDepsAppTests.cs @@ -24,7 +24,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RestartProcessOnFileChange() { await _app.StartWatcherAsync(new[] { "--no-exit" }); @@ -43,7 +42,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RestartProcessThatTerminatesAfterFileChange() { await _app.StartWatcherAsync(); diff --git a/src/Tools/dotnet-watch/test/ProgramTests.cs b/src/Tools/dotnet-watch/test/ProgramTests.cs index 1b3f33c5b9..9aa2f540cc 100644 --- a/src/Tools/dotnet-watch/test/ProgramTests.cs +++ b/src/Tools/dotnet-watch/test/ProgramTests.cs @@ -24,7 +24,6 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests } [Fact] - [QuarantinedTest] public async Task ConsoleCancelKey() { _tempDir From 6a4d79cfb8f8f93bad9ab9a041216ecb32e645fa Mon Sep 17 00:00:00 2001 From: Brennan Date: Mon, 22 Jun 2020 20:21:13 -0700 Subject: [PATCH 011/100] Fix java pack on local builds (#23237) --- .../clients/java/signalr/signalr.client.java.Tests.javaproj | 2 +- .../signalr/src/main/java/com/microsoft/signalr/Version.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SignalR/clients/java/signalr/signalr.client.java.Tests.javaproj b/src/SignalR/clients/java/signalr/signalr.client.java.Tests.javaproj index 6a1851569e..84771b3fe4 100644 --- a/src/SignalR/clients/java/signalr/signalr.client.java.Tests.javaproj +++ b/src/SignalR/clients/java/signalr/signalr.client.java.Tests.javaproj @@ -78,7 +78,7 @@ - $(GradleOptions) -PpackageVersion="$(PackageVersion)" + $(GradleOptions) -PpackageVersion="$(PackageVersion)" chmod +x ./gradlew && ./gradlew $(GradleOptions) test call gradlew $(GradleOptions) test diff --git a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Version.java b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Version.java index 4c73a498f6..3877f515be 100644 --- a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Version.java +++ b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Version.java @@ -6,6 +6,6 @@ package com.microsoft.signalr; class Version { public static String getDetailedVersion() { - return "99.99.99-dev"; + return "5.0.0-dev"; } } From a1c226e4f35703e6a6ac25e7d03ee0eec2314518 Mon Sep 17 00:00:00 2001 From: Brennan Date: Tue, 23 Jun 2020 10:46:03 -0700 Subject: [PATCH 012/100] [SignalR] Move to generic host (#22602) --- .../ref/Microsoft.AspNetCore.Hosting.csproj | 2 +- .../src/Microsoft.AspNetCore.Hosting.csproj | 4 +- .../FunctionalTests/HubConnectionTests.cs | 108 +++++++++--------- .../HubProtocolVersionTests.cs | 8 +- .../clients/ts/FunctionalTests/Program.cs | 106 +++++++++-------- .../test/MapConnectionHandlerTests.cs | 68 ++++++----- .../Tests.Utils/InProcessTestServer.cs | 44 ++++--- ...soft.AspNetCore.SignalR.Tests.Utils.csproj | 2 +- .../samples/JwtSample/JwtSample.csproj | 2 +- src/SignalR/samples/JwtSample/Program.cs | 30 +++-- src/SignalR/samples/SignalRSamples/Program.cs | 50 ++++---- src/SignalR/samples/SocialWeather/Program.cs | 28 +++-- .../SocialWeather/SocialWeather.csproj | 2 +- .../server/SignalR/test/EndToEndTests.cs | 32 +++--- .../server/SignalR/test/MapSignalRTests.cs | 34 +++--- .../SignalR/test/WebSocketsTransportTests.cs | 12 +- .../test/RedisServerFixture.cs | 29 +++-- 17 files changed, 306 insertions(+), 255 deletions(-) diff --git a/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.csproj b/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.csproj index 72e71d1c31..11eb4ad78e 100644 --- a/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.csproj +++ b/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj index c78cef809d..c0e3e77284 100644 --- a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj +++ b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core hosting infrastructure and startup logic for web applications. @@ -26,7 +26,7 @@ - + diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs index 39f99f7ff0..1e1de9abe4 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs @@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CheckFixedMessage(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -125,7 +125,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } var protocol = HubProtocols["json"]; - using (var server = await StartServer(ExpectedError)) + await using (var server = await StartServer(ExpectedError)) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ClientCanConnectToServerWithLowerMinimumProtocol() { var protocol = HubProtocols["json"]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -185,7 +185,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanSendAndReceiveMessage(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); @@ -214,7 +214,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanSendNull(string protocolName) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.LongPolling, protocol, LoggerFactory); try @@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStopAndStartConnection(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); @@ -275,7 +275,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanAccessConnectionIdFromHubConnection(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -310,7 +310,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStartConnectionFromClosedEvent(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); const string originalMessage = "SignalR"; @@ -372,7 +372,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task MethodsAreCaseInsensitive(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); @@ -402,7 +402,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanInvokeFromOnHandler(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; @@ -442,7 +442,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncCoreTest(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -477,7 +477,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStreamToHubWithIAsyncEnumerableMethodArg(string protocolName) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.WebSockets, protocol, LoggerFactory); try @@ -523,7 +523,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncTest(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -558,7 +558,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncDoesNotStartIfTokenAlreadyCanceled(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -595,7 +595,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncCanBeCanceled(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -643,7 +643,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } var protocol = HubProtocols[protocolName]; - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -679,7 +679,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanInvokeClientMethodFromServer(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; @@ -713,7 +713,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task InvokeNonExistantClientMethodFromServer(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); var closeTcs = new TaskCompletionSource(); @@ -755,7 +755,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStreamClientMethodFromServer(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -785,7 +785,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStreamToAndFromClientInSameInvocation(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -822,7 +822,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStreamToServerWithIAsyncEnumerable(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -869,7 +869,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanCancelIAsyncEnumerableClientToServerUpload(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -922,7 +922,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncCanBeCanceledThroughGetAsyncEnumerator(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -963,7 +963,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanCloseStreamMethodEarly(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -1004,7 +1004,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamDoesNotStartIfTokenAlreadyCanceled(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -1039,7 +1039,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } var protocol = HubProtocols[protocolName]; - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -1067,7 +1067,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfHubMethodCannotBeResolved(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1094,7 +1094,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfHubMethodCannotBeResolvedAndArgumentsPassedIn(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1121,7 +1121,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionOnHubMethodArgumentCountMismatch(string hubProtocolName) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.LongPolling, hubProtocol, LoggerFactory); try @@ -1148,7 +1148,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionOnHubMethodArgumentTypeMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1175,7 +1175,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfStreamingHubMethodCannotBeResolved(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1203,7 +1203,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionOnStreamingHubMethodArgumentCountMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1231,7 +1231,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionOnStreamingHubMethodArgumentTypeMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1259,7 +1259,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfNonStreamMethodInvokedWithStreamAsync(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1286,7 +1286,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfStreamMethodInvokedWithInvoke(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1313,7 +1313,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfBuildingAsyncEnumeratorIsNotPossible(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1349,7 +1349,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests }; var protocol = HubProtocols[protocolName]; - using (var server = await StartServer(write => write.EventId.Name == "FailedWritingMessage")) + await using (var server = await StartServer(write => write.EventId.Name == "FailedWritingMessage")) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.WebSockets, protocol, LoggerFactory); var closedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -1396,7 +1396,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests }; var protocol = HubProtocols[protocolName]; - using (var server = await StartServer(write => write.EventId.Name == "FailedWritingMessage")) + await using (var server = await StartServer(write => write.EventId.Name == "FailedWritingMessage")) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.LongPolling, protocol, LoggerFactory); var closedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -1436,7 +1436,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests var hubProtocol = HubProtocols.First().Value; var transportType = TransportTypes().First().Cast().First(); - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); await connection.StartAsync().OrTimeout(); @@ -1453,7 +1453,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientCanUseJwtBearerTokenForAuthentication(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { async Task AccessTokenProvider() { @@ -1496,7 +1496,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests return writeContext.Exception is HttpRequestException; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1518,7 +1518,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientCanUseJwtBearerTokenForAuthenticationWhenRedirected(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1546,7 +1546,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientCanSendHeaders(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1577,7 +1577,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task UserAgentIsSet() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1619,7 +1619,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task UserAgentCanBeCleared() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1654,7 +1654,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task UserAgentCanBeSet() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1690,7 +1690,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [WebSocketsSupportedCondition] public async Task WebSocketOptionsAreApplied() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { // System.Net has a HttpTransportType type which means we need to fully-qualify this rather than 'use' the namespace var cookieJar = new System.Net.CookieContainer(); @@ -1724,7 +1724,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task CheckHttpConnectionFeatures() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1760,7 +1760,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task UserIdProviderCanAccessHttpContext() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1791,7 +1791,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task NegotiationSkipsServerSentEventsWhenUsingBinaryProtocol() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1821,7 +1821,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task StopCausesPollToReturnImmediately() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { PollTrackingMessageHandler pollTracker = null; var hubConnection = new HubConnectionBuilder() @@ -1869,7 +1869,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests writeContext.EventId.Name == "ReconnectingWithError"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connection = CreateHubConnection( server.Url, @@ -1931,7 +1931,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests writeContext.EventId.Name == "ReconnectingWithError"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1991,7 +1991,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests writeContext.EventId.Name == "ReconnectingWithError"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubProtocolVersionTests.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubProtocolVersionTests.cs index a7240053b8..fbf5ea3fd6 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubProtocolVersionTests.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubProtocolVersionTests.cs @@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientUsingOldCallWithOriginalProtocol(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientUsingOldCallWithNewProtocol(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientUsingNewCallWithNewProtocol(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var httpConnectionFactory = new HttpConnectionFactory( Options.Create(new HttpConnectionOptions @@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests return writeContext.LoggerName == typeof(HubConnection).FullName; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) diff --git a/src/SignalR/clients/ts/FunctionalTests/Program.cs b/src/SignalR/clients/ts/FunctionalTests/Program.cs index 2f67e3d5cd..bc1cc0a323 100644 --- a/src/SignalR/clients/ts/FunctionalTests/Program.cs +++ b/src/SignalR/clients/ts/FunctionalTests/Program.cs @@ -5,7 +5,9 @@ using System; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Win32; @@ -13,7 +15,7 @@ namespace FunctionalTests { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { string url = null; for (var i = 0; i < args.Length; i++) @@ -27,65 +29,69 @@ namespace FunctionalTests } } - var hostBuilder = new WebHostBuilder() - .ConfigureLogging(factory => + var hostBuilder = new HostBuilder() + .ConfigureWebHost(webHostBuilder => { - factory.AddConsole(options => + webHostBuilder + .ConfigureLogging(factory => { - options.IncludeScopes = true; - options.TimestampFormat = "[HH:mm:ss] "; - options.UseUtcTimestamp = true; - }); - factory.AddDebug(); - factory.SetMinimumLevel(LogLevel.Debug); - }) - .UseKestrel((builderContext, options) => - { - options.ConfigureHttpsDefaults(httpsOptions => - { - bool useRSA = false; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + factory.AddConsole(options => { - // Detect Win10+ - var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); - var major = key.GetValue("CurrentMajorVersionNumber") as int?; - var minor = key.GetValue("CurrentMinorVersionNumber") as int?; + options.IncludeScopes = true; + options.TimestampFormat = "[HH:mm:ss] "; + options.UseUtcTimestamp = true; + }); + factory.AddDebug(); + factory.SetMinimumLevel(LogLevel.Debug); + }) + .UseKestrel((builderContext, options) => + { + options.ConfigureHttpsDefaults(httpsOptions => + { + bool useRSA = false; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Detect Win10+ + var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); + var major = key.GetValue("CurrentMajorVersionNumber") as int?; + var minor = key.GetValue("CurrentMinorVersionNumber") as int?; - if (major.HasValue && minor.HasValue) + if (major.HasValue && minor.HasValue) + { + useRSA = true; + } + } + else { useRSA = true; } - } - else - { - useRSA = true; - } - if (useRSA) - { - // RSA cert, won't work on Windows 8.1 & Windows 2012 R2 using HTTP2, and ECC won't work in some Node environments - var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCert.pfx"); - httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); - } - else - { - // ECC cert, works on Windows 8.1 & Windows 2012 R2 using HTTP2 - var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCertECC.pfx"); - httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); - } - }); - }) - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup(); + if (useRSA) + { + // RSA cert, won't work on Windows 8.1 & Windows 2012 R2 using HTTP2, and ECC won't work in some Node environments + var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCert.pfx"); + httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); + } + else + { + // ECC cert, works on Windows 8.1 & Windows 2012 R2 using HTTP2 + var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCertECC.pfx"); + httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); + } + }); + }) + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup(); - if (!string.IsNullOrEmpty(url)) - { - Console.WriteLine($"Forcing URL to: {url}"); - hostBuilder.UseUrls(url); - } + if (!string.IsNullOrEmpty(url)) + { + Console.WriteLine($"Forcing URL to: {url}"); + webHostBuilder.UseUrls(url); + } + }); - hostBuilder.Build().Run(); + return hostBuilder.Build().RunAsync(); } } } diff --git a/src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs b/src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs index d603c0d083..7b734ac2fa 100644 --- a/src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs +++ b/src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs @@ -13,11 +13,13 @@ using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors.Infrastructure; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; @@ -305,7 +307,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests [WebSocketsSupportedCondition] public async Task MapConnectionHandlerWithWebSocketSubProtocolSetsProtocol() { - var host = BuildWebHost("/socket", + using var host = BuildWebHost("/socket", options => options.WebSockets.SubProtocolSelector = subprotocols => { Assert.Equal(new[] { "protocol1", "protocol2" }, subprotocols.ToArray()); @@ -314,7 +316,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests await host.StartAsync(); - var feature = host.ServerFeatures.Get(); + var feature = host.Services.GetService().Features.Get(); var address = feature.Addresses.First().Replace("http", "ws") + "/socket"; var client = new ClientWebSocket(); @@ -377,44 +379,52 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests } } - private IWebHost BuildWebHost(Action configure) + private IHost BuildWebHost(Action configure) { - return new WebHostBuilder() - .UseKestrel() - .ConfigureServices(services => + return new HostBuilder() + .ConfigureWebHost(webHostBuilder => { - services.AddConnections(); + webHostBuilder + .UseKestrel() + .ConfigureServices(services => + { + services.AddConnections(); + }) + .Configure(app => + { + app.UseRouting(); + app.UseEndpoints(endpoints => configure(endpoints)); + }) + .UseUrls("http://127.0.0.1:0"); }) - .Configure(app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => configure(endpoints)); - }) - .UseUrls("http://127.0.0.1:0") .Build(); } - private IWebHost BuildWebHost(string path, Action configureOptions) where TConnectionHandler : ConnectionHandler + private IHost BuildWebHost(string path, Action configureOptions) where TConnectionHandler : ConnectionHandler { - return new WebHostBuilder() - .UseUrls("http://127.0.0.1:0") - .UseKestrel() - .ConfigureServices(services => + return new HostBuilder() + .ConfigureWebHost(webHostBuilder => { - services.AddConnections(); - }) - .Configure(app => - { - app.UseRouting(); - app.UseEndpoints(routes => + webHostBuilder + .UseUrls("http://127.0.0.1:0") + .UseKestrel() + .ConfigureServices(services => { - routes.MapConnectionHandler(path, configureOptions); + services.AddConnections(); + }) + .Configure(app => + { + app.UseRouting(); + app.UseEndpoints(routes => + { + routes.MapConnectionHandler(path, configureOptions); + }); + }) + .ConfigureLogging(factory => + { + factory.AddXunit(_output, LogLevel.Trace); }); }) - .ConfigureLogging(factory => - { - factory.AddXunit(_output, LogLevel.Trace); - }) .Build(); } } diff --git a/src/SignalR/common/testassets/Tests.Utils/InProcessTestServer.cs b/src/SignalR/common/testassets/Tests.Utils/InProcessTestServer.cs index 631220c7de..d50c425528 100644 --- a/src/SignalR/common/testassets/Tests.Utils/InProcessTestServer.cs +++ b/src/SignalR/common/testassets/Tests.Utils/InProcessTestServer.cs @@ -9,16 +9,16 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Testing; namespace Microsoft.AspNetCore.SignalR.Tests { - public abstract class InProcessTestServer : IDisposable + public abstract class InProcessTestServer : IAsyncDisposable { internal abstract event Action ServerLogged; @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public abstract string Url { get; } - public abstract void Dispose(); + public abstract ValueTask DisposeAsync(); } public class InProcessTestServer : InProcessTestServer @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { private readonly ILoggerFactory _loggerFactory; private readonly ILogger _logger; - private IWebHost _host; + private IHost _host; private IHostApplicationLifetime _lifetime; private readonly IDisposable _logToken; private readonly IDisposable _extraDisposable; @@ -91,15 +91,18 @@ namespace Microsoft.AspNetCore.SignalR.Tests // We're using 127.0.0.1 instead of localhost to ensure that we use IPV4 across different OSes var url = "http://127.0.0.1:0"; - _host = new WebHostBuilder() - .ConfigureLogging(builder => builder + _host = new HostBuilder() + .ConfigureWebHost(webHostBuilder => + { + webHostBuilder + .ConfigureLogging(builder => builder .SetMinimumLevel(LogLevel.Trace) .AddProvider(new ForwardingLoggerProvider(_loggerFactory))) - .UseStartup(typeof(TStartup)) - .UseKestrel() - .UseUrls(url) - .UseContentRoot(Directory.GetCurrentDirectory()) - .Build(); + .UseStartup(typeof(TStartup)) + .UseKestrel() + .UseUrls(url) + .UseContentRoot(Directory.GetCurrentDirectory()); + }).Build(); _logger.LogInformation("Starting test server..."); var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); @@ -116,7 +119,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests _logger.LogInformation("Test Server started"); // Get the URL from the server - _url = _host.ServerFeatures.Get().Addresses.Single(); + _url = _host.Services.GetService().Features.Get().Addresses.Single(); _lifetime = _host.Services.GetRequiredService(); _lifetime.ApplicationStopped.Register(() => @@ -144,12 +147,19 @@ namespace Microsoft.AspNetCore.SignalR.Tests return builder.ToString(); } - public override void Dispose() + public override async ValueTask DisposeAsync() { - _extraDisposable?.Dispose(); - _logger.LogInformation("Shutting down test server"); - _host.Dispose(); - _loggerFactory.Dispose(); + try + { + _extraDisposable?.Dispose(); + _logger.LogInformation("Start shutting down test server"); + } + finally + { + await _host.StopAsync(); + _host.Dispose(); + _loggerFactory.Dispose(); + } } private class ForwardingLoggerProvider : ILoggerProvider diff --git a/src/SignalR/common/testassets/Tests.Utils/Microsoft.AspNetCore.SignalR.Tests.Utils.csproj b/src/SignalR/common/testassets/Tests.Utils/Microsoft.AspNetCore.SignalR.Tests.Utils.csproj index 86cb17cb5f..dc4198b924 100644 --- a/src/SignalR/common/testassets/Tests.Utils/Microsoft.AspNetCore.SignalR.Tests.Utils.csproj +++ b/src/SignalR/common/testassets/Tests.Utils/Microsoft.AspNetCore.SignalR.Tests.Utils.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) diff --git a/src/SignalR/samples/JwtSample/JwtSample.csproj b/src/SignalR/samples/JwtSample/JwtSample.csproj index 552c9d63f2..b8ac2dc1a7 100644 --- a/src/SignalR/samples/JwtSample/JwtSample.csproj +++ b/src/SignalR/samples/JwtSample/JwtSample.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) diff --git a/src/SignalR/samples/JwtSample/Program.cs b/src/SignalR/samples/JwtSample/Program.cs index a4bff29a37..06050394b7 100644 --- a/src/SignalR/samples/JwtSample/Program.cs +++ b/src/SignalR/samples/JwtSample/Program.cs @@ -1,29 +1,35 @@ -// 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.IO; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace JwtSample { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { - new WebHostBuilder() - .ConfigureLogging(factory => + return Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => { - factory.AddConsole(); - factory.AddFilter("Console", level => level >= LogLevel.Information); - factory.AddDebug(); + webHostBuilder + .ConfigureLogging(factory => + { + factory.AddConsole(); + factory.AddFilter("Console", level => level >= LogLevel.Information); + factory.AddDebug(); + }) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup(); }) - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() .Build() - .Run(); + .RunAsync(); } } } diff --git a/src/SignalR/samples/SignalRSamples/Program.cs b/src/SignalR/samples/SignalRSamples/Program.cs index 2f932a18a4..c56a2c5b59 100644 --- a/src/SignalR/samples/SignalRSamples/Program.cs +++ b/src/SignalR/samples/SignalRSamples/Program.cs @@ -3,9 +3,11 @@ using System.IO; using System.Net; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using SignalRSamples.Hubs; @@ -13,36 +15,40 @@ namespace SignalRSamples { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { var config = new ConfigurationBuilder() .AddCommandLine(args) .Build(); - var host = new WebHostBuilder() - .UseConfiguration(config) - .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true") - .ConfigureLogging(factory => + var host = Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => { - factory.AddConsole(); - }) - .UseKestrel(options => - { - // Default port - options.ListenLocalhost(5000); - - // Hub bound to TCP end point - options.Listen(IPAddress.Any, 9001, builder => + webHostBuilder + .UseConfiguration(config) + .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true") + .ConfigureLogging((c, factory) => { - builder.UseHub(); - }); - }) - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() - .Build(); + factory.AddConfiguration(c.Configuration.GetSection("Logging")); + factory.AddConsole(); + }) + .UseKestrel(options => + { + // Default port + options.ListenLocalhost(5000); - host.Run(); + // Hub bound to TCP end point + options.Listen(IPAddress.Any, 9001, builder => + { + builder.UseHub(); + }); + }) + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup(); + }).Build(); + + return host.RunAsync(); } } } diff --git a/src/SignalR/samples/SocialWeather/Program.cs b/src/SignalR/samples/SocialWeather/Program.cs index 426f89226b..24169976a6 100644 --- a/src/SignalR/samples/SocialWeather/Program.cs +++ b/src/SignalR/samples/SocialWeather/Program.cs @@ -2,29 +2,35 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.IO; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace SocialWeather { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { - var host = new WebHostBuilder() - .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true") - .ConfigureLogging(factory => + var host = Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => { - factory.AddConsole(); - factory.AddFilter("Console", level => level >= LogLevel.Information); + webHostBuilder + .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true") + .ConfigureLogging(factory => + { + factory.AddConsole(); + factory.AddFilter("Console", level => level >= LogLevel.Information); + }) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup(); }) - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() .Build(); - host.Run(); + return host.RunAsync(); } } } diff --git a/src/SignalR/samples/SocialWeather/SocialWeather.csproj b/src/SignalR/samples/SocialWeather/SocialWeather.csproj index ea9308fee5..fe8e362e2c 100644 --- a/src/SignalR/samples/SocialWeather/SocialWeather.csproj +++ b/src/SignalR/samples/SocialWeather/SocialWeather.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) diff --git a/src/SignalR/server/SignalR/test/EndToEndTests.cs b/src/SignalR/server/SignalR/test/EndToEndTests.cs index 7461b2e90e..caebf870c6 100644 --- a/src/SignalR/server/SignalR/test/EndToEndTests.cs +++ b/src/SignalR/server/SignalR/test/EndToEndTests.cs @@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [Fact] public async Task CanStartAndStopConnectionUsingDefaultTransport() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var url = server.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. @@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorStartingTransport"; } - using (var server = await StartServer(expectedErrorsFilter: ExpectedErrors)) + await using (var server = await StartServer(expectedErrorsFilter: ExpectedErrors)) { var url = server.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. @@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [LogLevel(LogLevel.Trace)] public async Task CanStartAndStopConnectionUsingGivenTransport(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var url = server.Url + "/echo"; var connection = new HttpConnection(new HttpConnectionOptions { Url = new Uri(url), Transports = transportType, DefaultTransferFormat = TransferFormat.Text }, LoggerFactory); @@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTest() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -125,7 +125,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsReceivesAndSendsPartialFramesTest() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -164,7 +164,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task HttpRequestsNotSentWhenWebSocketsTransportRequestedAndSkipNegotiationSet() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); var url = server.Url + "/echo"; @@ -214,7 +214,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [InlineData(HttpTransportType.ServerSentEvents)] public async Task HttpConnectionThrowsIfSkipNegotiationSetAndTransportIsNotWebSockets(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); var url = server.Url + "/echo"; @@ -257,7 +257,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [LogLevel(LogLevel.Trace)] public async Task ConnectionCanSendAndReceiveMessages(HttpTransportType transportType, TransferFormat requestedTransferFormat) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -315,7 +315,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public async Task ConnectionCanSendAndReceiveDifferentMessageSizesWebSocketsTransport(int length) { var message = new string('A', length); - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -379,7 +379,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -403,7 +403,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorStartingTransport"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -433,7 +433,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -469,7 +469,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -539,7 +539,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests private async Task ServerClosesConnectionWithErrorIfHubCannotBeCreated(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -604,7 +604,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -643,7 +643,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); diff --git a/src/SignalR/server/SignalR/test/MapSignalRTests.cs b/src/SignalR/server/SignalR/test/MapSignalRTests.cs index 8f1a79dc4a..695a5683c7 100644 --- a/src/SignalR/server/SignalR/test/MapSignalRTests.cs +++ b/src/SignalR/server/SignalR/test/MapSignalRTests.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Xunit; namespace Microsoft.AspNetCore.SignalR.Tests @@ -29,9 +30,11 @@ namespace Microsoft.AspNetCore.SignalR.Tests public void NotAddingSignalRServiceThrows() { var executedConfigure = false; - var builder = new WebHostBuilder(); + var builder = new HostBuilder(); - builder + builder.ConfigureWebHost(webHostBuilder => + { + webHostBuilder .UseKestrel() .ConfigureServices(services => { @@ -54,6 +57,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests "'IServiceCollection.AddSignalR' inside the call to 'ConfigureServices(...)' in the application startup code.", ex.Message); }) .UseUrls("http://127.0.0.1:0"); + }); using (var host = builder.Build()) { @@ -338,20 +342,24 @@ namespace Microsoft.AspNetCore.SignalR.Tests { } - private IWebHost BuildWebHost(Action configure) + private IHost BuildWebHost(Action configure) { - return new WebHostBuilder() - .UseKestrel() - .ConfigureServices(services => + return new HostBuilder() + .ConfigureWebHost(webHostBuilder => { - services.AddSignalR(); + webHostBuilder + .UseKestrel() + .ConfigureServices(services => + { + services.AddSignalR(); + }) + .Configure(app => + { + app.UseRouting(); + app.UseEndpoints(endpoints => configure(endpoints)); + }) + .UseUrls("http://127.0.0.1:0"); }) - .Configure(app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => configure(endpoints)); - }) - .UseUrls("http://127.0.0.1:0") .Build(); } } diff --git a/src/SignalR/server/SignalR/test/WebSocketsTransportTests.cs b/src/SignalR/server/SignalR/test/WebSocketsTransportTests.cs index 2c059c3edc..6736265a72 100644 --- a/src/SignalR/server/SignalR/test/WebSocketsTransportTests.cs +++ b/src/SignalR/server/SignalR/test/WebSocketsTransportTests.cs @@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTransportStopsSendAndReceiveLoopsWhenTransportIsStopped() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/echo"), @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTransportSendsUserAgent() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/httpheader"), @@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTransportSendsXRequestedWithHeader() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/httpheader"), @@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTransportStopsWhenConnectionChannelClosed() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/echo"), @@ -137,7 +137,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [InlineData(TransferFormat.Binary)] public async Task WebSocketsTransportStopsWhenConnectionClosedByTheServer(TransferFormat transferFormat) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/echoAndClose"), transferFormat); @@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [InlineData(TransferFormat.Binary)] public async Task WebSocketsTransportSetsTransferFormat(TransferFormat transferFormat) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); diff --git a/src/SignalR/server/StackExchangeRedis/test/RedisServerFixture.cs b/src/SignalR/server/StackExchangeRedis/test/RedisServerFixture.cs index ab063ee02a..50ecafbb9f 100644 --- a/src/SignalR/server/StackExchangeRedis/test/RedisServerFixture.cs +++ b/src/SignalR/server/StackExchangeRedis/test/RedisServerFixture.cs @@ -6,12 +6,11 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Testing; using Xunit; namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests { - public class RedisServerFixture : IAsyncLifetime, IDisposable + public class RedisServerFixture : IAsyncLifetime where TStartup : class { public InProcessTestServer FirstServer { get; private set; } @@ -37,13 +36,24 @@ namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests Docker.Default.Start(_logger); } - public Task DisposeAsync() + public async Task DisposeAsync() { - return Task.CompletedTask; + if (Docker.Default != null) + { + await FirstServer.DisposeAsync(); + await SecondServer.DisposeAsync(); + Docker.Default.Stop(_logger); + _logToken.Dispose(); + } } public async Task InitializeAsync() { + if (Docker.Default == null) + { + return; + } + FirstServer = await StartServer(); SecondServer = await StartServer(); } @@ -60,16 +70,5 @@ namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests throw; } } - - public void Dispose() - { - if (Docker.Default != null) - { - FirstServer.Dispose(); - SecondServer.Dispose(); - Docker.Default.Stop(_logger); - _logToken.Dispose(); - } - } } } From cb35b902262535d831209996a2a0053f717dadb3 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2020 18:02:28 +0000 Subject: [PATCH 013/100] Update dependencies from https://github.com/dotnet/runtime build 20200622.7 (#23255) System.ComponentModel.Annotations , System.Diagnostics.DiagnosticSource , System.Diagnostics.EventLog , Microsoft.Extensions.Logging.Configuration , Microsoft.Extensions.Logging.Console , Microsoft.Extensions.Logging.Debug , Microsoft.Extensions.Logging.EventLog , Microsoft.Extensions.Logging.EventSource , Microsoft.Extensions.Logging.TraceSource , Microsoft.Extensions.Options , Microsoft.Extensions.Options.ConfigurationExtensions , Microsoft.Extensions.Options.DataAnnotations , Microsoft.Extensions.Primitives , Microsoft.Extensions.Logging.Abstractions , Microsoft.Extensions.Logging , Microsoft.Extensions.Internal.Transport , Microsoft.Extensions.Http , Microsoft.Extensions.Caching.Abstractions , Microsoft.Extensions.Caching.Memory , Microsoft.Extensions.Configuration , Microsoft.Extensions.Configuration.Abstractions , Microsoft.Extensions.Configuration.Binder , Microsoft.Extensions.Configuration.CommandLine , Microsoft.Extensions.Configuration.EnvironmentVariables , Microsoft.Extensions.Configuration.FileExtensions , Microsoft.Extensions.Configuration.Ini , Microsoft.Extensions.Configuration.Json , Microsoft.Extensions.Configuration.UserSecrets , Microsoft.Extensions.DependencyInjection , Microsoft.Extensions.DependencyInjection.Abstractions , Microsoft.Extensions.DependencyModel , Microsoft.Extensions.FileProviders.Abstractions , Microsoft.Extensions.FileProviders.Composite , Microsoft.Extensions.FileProviders.Physical , Microsoft.Extensions.FileSystemGlobbing , Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.Extensions.Hosting , Microsoft.Extensions.Hosting.Abstractions , Microsoft.Extensions.Configuration.Xml , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NETCore.Platforms , Microsoft.Win32.Registry , Microsoft.Win32.SystemEvents , Microsoft.NETCore.App.Internal , Microsoft.NETCore.App.Ref , System.Drawing.Common , System.ServiceProcess.ServiceController , System.Text.Encodings.Web , System.Text.Json , System.Threading.Channels , System.Windows.Extensions , System.Security.Principal.Windows , System.Security.Permissions , System.Security.Cryptography.Xml , System.IO.Pipelines , System.Net.Http.Json , System.Net.Http.WinHttpHandler , System.Net.WebSockets.WebSocketProtocol , System.Reflection.Metadata , System.Runtime.CompilerServices.Unsafe , System.Security.Cryptography.Cng , System.Security.Cryptography.Pkcs From Version 5.0.0-preview.7.20321.2 -> To Version 5.0.0-preview.7.20322.7 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 248 ++++++++++++++++++++-------------------- eng/Versions.props | 124 ++++++++++---------- 2 files changed, 186 insertions(+), 186 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 79ac930ee6..df0e011a81 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -41,260 +41,260 @@ https://github.com/dotnet/efcore 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 1f4d0db2339c37d75723d063827fd2a4c6e2ecef + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index 1852a7c1ef..999857ae45 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,69 +66,69 @@ 3.7.0-4.20319.6 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 - 5.0.0-preview.7.20321.2 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20321.2 + 5.0.0-preview.7.20322.7 3.2.0 From c566677456ae2b066c3d6e1cd06fc5d025287a03 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2020 22:14:51 +0000 Subject: [PATCH 014/100] Update dependencies from https://github.com/dotnet/efcore build 20200623.2 (#23273) Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20322.6 -> To Version 5.0.0-preview.8.20323.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index df0e011a81..5e84dbbf0b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - 7f3e01aa6b00f0e3d61639a069d62033c8cf4bf5 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 999857ae45..e8977a9bad 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.8.20322.6 - 5.0.0-preview.8.20322.6 - 5.0.0-preview.8.20322.6 - 5.0.0-preview.8.20322.6 - 5.0.0-preview.8.20322.6 - 5.0.0-preview.8.20322.6 - 5.0.0-preview.8.20322.6 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 3.2.0 - 5.0.0-preview.8.20323.2 - 5.0.0-preview.8.20323.2 - 5.0.0-preview.8.20323.2 - 5.0.0-preview.8.20323.2 - 5.0.0-preview.8.20323.2 - 5.0.0-preview.8.20323.2 - 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.10 + 5.0.0-preview.8.20323.10 + 5.0.0-preview.8.20323.10 + 5.0.0-preview.8.20323.10 + 5.0.0-preview.8.20323.10 + 5.0.0-preview.8.20323.10 + 5.0.0-preview.8.20323.10 - + https://github.com/dotnet/runtime - d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 + d908270add914db0e9fb3ce72e93c410e8f0f95a - + https://github.com/dotnet/runtime - d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 + d908270add914db0e9fb3ce72e93c410e8f0f95a - + https://github.com/dotnet/runtime - d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 + d908270add914db0e9fb3ce72e93c410e8f0f95a https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index c52a5c1f67..311aa670d5 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,69 +66,69 @@ 3.7.0-4.20319.6 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20322.7 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20323.9 - 5.0.0-preview.7.20322.7 + 5.0.0-preview.8.20323.9 3.2.0 From 5155e11120cf7ee2e07383225057f66512f00fde Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Wed, 24 Jun 2020 15:17:33 +0100 Subject: [PATCH 021/100] Two minor perf tweaks in CORS and Localization middleware (#23190) * Use char instead of char[] for string.Split Use the newer overload for string.Split() that accepts a char instead of creating a char array. * Remove redundant bounds check Remove redundant bounds check for count of exactly 1 as that has already been checked to be true by the previous check. --- src/Middleware/CORS/src/Infrastructure/CorsPolicy.cs | 6 +++--- .../Localization/src/CookieRequestCultureProvider.cs | 7 ++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Middleware/CORS/src/Infrastructure/CorsPolicy.cs b/src/Middleware/CORS/src/Infrastructure/CorsPolicy.cs index 8c7529d30e..54f48fe16a 100644 --- a/src/Middleware/CORS/src/Infrastructure/CorsPolicy.cs +++ b/src/Middleware/CORS/src/Infrastructure/CorsPolicy.cs @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { get { - if (Headers == null || Headers.Count != 1 || Headers.Count == 1 && Headers[0] != "*") + if (Headers == null || Headers.Count != 1 || Headers[0] != "*") { return false; } @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { get { - if (Methods == null || Methods.Count != 1 || Methods.Count == 1 && Methods[0] != "*") + if (Methods == null || Methods.Count != 1 || Methods[0] != "*") { return false; } @@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { get { - if (Origins == null || Origins.Count != 1 || Origins.Count == 1 && Origins[0] != "*") + if (Origins == null || Origins.Count != 1 || Origins[0] != "*") { return false; } diff --git a/src/Middleware/Localization/src/CookieRequestCultureProvider.cs b/src/Middleware/Localization/src/CookieRequestCultureProvider.cs index 63b89fb611..5a17457848 100644 --- a/src/Middleware/Localization/src/CookieRequestCultureProvider.cs +++ b/src/Middleware/Localization/src/CookieRequestCultureProvider.cs @@ -4,7 +4,6 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Localization { @@ -13,7 +12,7 @@ namespace Microsoft.AspNetCore.Localization /// public class CookieRequestCultureProvider : RequestCultureProvider { - private static readonly char[] _cookieSeparator = new[] { '|' }; + private static readonly char _cookieSeparator = '|'; private static readonly string _culturePrefix = "c="; private static readonly string _uiCulturePrefix = "uic="; @@ -60,9 +59,7 @@ namespace Microsoft.AspNetCore.Localization throw new ArgumentNullException(nameof(requestCulture)); } - var seperator = _cookieSeparator[0].ToString(); - - return string.Join(seperator, + return string.Join(_cookieSeparator, $"{_culturePrefix}{requestCulture.Culture.Name}", $"{_uiCulturePrefix}{requestCulture.UICulture.Name}"); } From dad1ca68d7be1c8f91e12e46ecae6695cd5dea9d Mon Sep 17 00:00:00 2001 From: Brennan Date: Wed, 24 Jun 2020 12:29:11 -0700 Subject: [PATCH 022/100] Make RequestServices work for cloned longpolling HttpContext (#23014) --- .../src/Internal/HttpConnectionContext.cs | 6 + .../src/Internal/HttpConnectionDispatcher.cs | 15 +- .../test/HttpConnectionDispatcherTests.cs | 323 ++++++++++++++---- 3 files changed, 265 insertions(+), 79 deletions(-) diff --git a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs index ec7b124f8f..5958c7ef92 100644 --- a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs +++ b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs @@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Http.Connections.Features; using Microsoft.AspNetCore.Http.Connections.Internal.Transports; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Internal; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Http.Connections.Internal @@ -99,6 +100,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal // Used for testing only internal Task DisposeAndRemoveTask { get; set; } + // Used for LongPolling because we need to create a scope that spans the lifetime of multiple requests on the cloned HttpContext + internal IServiceScope ServiceScope { get; set; } + public Task TransportTask { get; set; } public Task PreviousPollTask { get; set; } = Task.CompletedTask; @@ -251,6 +255,8 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal (identity as IDisposable)?.Dispose(); } } + + ServiceScope?.Dispose(); } await disposeTask; diff --git a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs index 7f6477cab0..fab15305ce 100644 --- a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs +++ b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs @@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http.Connections.Internal.Transports; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Internal; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; @@ -537,8 +538,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal var existing = connection.HttpContext; if (existing == null) { - var httpContext = CloneHttpContext(context); - connection.HttpContext = httpContext; + CloneHttpContext(context, connection); } else { @@ -606,7 +606,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal } } - private static HttpContext CloneHttpContext(HttpContext context) + private static void CloneHttpContext(HttpContext context, HttpConnectionContext connection) { // The reason we're copying the base features instead of the HttpContext properties is // so that we can get all of the logic built into DefaultHttpContext to extract higher level @@ -660,14 +660,13 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal CloneUser(newHttpContext, context); - // Making request services function property could be tricky and expensive as it would require - // DI scope per connection. It would also mean that services resolved in middleware leading up to here - // wouldn't be the same instance (but maybe that's fine). For now, we just return an empty service provider - newHttpContext.RequestServices = EmptyServiceProvider.Instance; + connection.ServiceScope = context.RequestServices.CreateScope(); + newHttpContext.RequestServices = connection.ServiceScope.ServiceProvider; // REVIEW: This extends the lifetime of anything that got put into HttpContext.Items newHttpContext.Items = new Dictionary(context.Items); - return newHttpContext; + + connection.HttpContext = newHttpContext; } private async Task GetConnectionAsync(HttpContext context) diff --git a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs index bed8bba4db..85418c85c3 100644 --- a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs +++ b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs @@ -510,6 +510,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests values["negotiateVersion"] = "1"; var qs = new QueryCollection(values); context.Request.Query = qs; + context.RequestServices = services.BuildServiceProvider(); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.Use(next => @@ -723,6 +724,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests context.Connection.RemoteIpAddress = IPAddress.IPv6Any; context.Connection.RemotePort = 43456; context.SetEndpoint(new Endpoint(null, null, "TestName")); + context.RequestServices = services.BuildServiceProvider(); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); @@ -942,12 +944,12 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); + var services = new ServiceCollection(); + services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); SetTransport(context, HttpTransportType.ServerSentEvents); - var services = new ServiceCollection(); - services.AddSingleton(); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -976,11 +978,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests connection.TransportType = HttpTransportType.ServerSentEvents; var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - SetTransport(context, HttpTransportType.ServerSentEvents); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, HttpTransportType.ServerSentEvents); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1004,10 +1006,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1035,10 +1037,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1128,9 +1130,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var connection = manager.CreateConnection(); connection.TransportType = HttpTransportType.LongPolling; var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1161,10 +1163,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var connection = manager.CreateConnection(); connection.TransportType = HttpTransportType.ServerSentEvents; var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - SetTransport(context, connection.TransportType); var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, connection.TransportType); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1199,10 +1201,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests connection.TransportType = HttpTransportType.WebSockets; var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); var sync = new SyncPoint(); - var context = MakeRequest("/foo", connection); - SetTransport(context, connection.TransportType, sync); var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, connection.TransportType, sync); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1232,11 +1234,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - SetTransport(context, HttpTransportType.WebSockets); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, HttpTransportType.WebSockets); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1262,14 +1264,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context1 = MakeRequest("/foo", connection); - var context2 = MakeRequest("/foo", connection); + var services = new ServiceCollection(); + services.AddSingleton(); + var context1 = MakeRequest("/foo", connection, services); + var context2 = MakeRequest("/foo", connection, services); SetTransport(context1, transportType); SetTransport(context2, transportType); - var services = new ServiceCollection(); - services.AddSingleton(); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1305,11 +1307,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context1 = MakeRequest("/foo", connection); - var context2 = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context1 = MakeRequest("/foo", connection, services); + var context2 = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1369,11 +1371,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context1 = MakeRequest("/foo", connection); - var context2 = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context1 = MakeRequest("/foo", connection, services); + var context2 = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1432,11 +1434,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - SetTransport(context, transportType); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, transportType); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1459,10 +1461,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1494,11 +1496,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - SetTransport(context, HttpTransportType.ServerSentEvents); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, HttpTransportType.ServerSentEvents); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1529,10 +1531,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1577,12 +1579,12 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var app = builder.Build(); var options = new HttpConnectionDispatcherOptions(); - var context1 = MakeRequest("/foo", connection); + var context1 = MakeRequest("/foo", connection, services); // This is the initial poll to make sure things are setup var task1 = dispatcher.ExecuteAsync(context1, options, app); Assert.True(task1.IsCompleted); task1 = dispatcher.ExecuteAsync(context1, options, app); - var context2 = MakeRequest("/foo", connection); + var context2 = MakeRequest("/foo", connection, services); var task2 = dispatcher.ExecuteAsync(context2, options, app); // Task 1 should finish when request 2 arrives @@ -1615,11 +1617,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - SetTransport(context, transportType); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, transportType); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1751,10 +1753,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1783,11 +1785,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - SetTransport(context, transportType); - var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(); + var context = MakeRequest("/foo", connection, serviceCollection); + SetTransport(context, transportType); + var services = serviceCollection.BuildServiceProvider(); var builder = new ConnectionBuilder(services); builder.UseConnectionHandler(); @@ -1824,10 +1826,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1877,10 +1879,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1926,10 +1928,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -1992,7 +1994,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests }; { var options = new HttpConnectionDispatcherOptions(); - var context = MakeRequest("/foo", connection); + var context = MakeRequest("/foo", connection, new ServiceCollection()); await dispatcher.ExecuteAsync(context, options, connectionDelegate).OrTimeout(); // second poll should have data @@ -2008,7 +2010,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests waitForMessageTcs2.SetResult(); await messageTcs2.Task.OrTimeout(); - context = MakeRequest("/foo", connection); + context = MakeRequest("/foo", connection, new ServiceCollection()); ms.Seek(0, SeekOrigin.Begin); context.Response.Body = ms; // This is the third poll which gets the final message after the app is complete @@ -2217,7 +2219,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var sendTask = dispatcher.ExecuteAsync(context, options, app).OrTimeout(); Assert.False(sendTask.IsCompleted); - var pollContext = MakeRequest("/foo", connection); + var pollContext = MakeRequest("/foo", connection, services); // This should unblock the send that is waiting because of backpressure // Testing deadlock regression where pipe backpressure would hold the same lock that poll would use await dispatcher.ExecuteAsync(pollContext, options, app).OrTimeout(); @@ -2253,12 +2255,12 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var app = builder.Build(); var options = new HttpConnectionDispatcherOptions(); - var context = MakeRequest("/foo", connection); + var context = MakeRequest("/foo", connection, services); // Initial poll will complete immediately await dispatcher.ExecuteAsync(context, options, app).OrTimeout(); - var pollContext = MakeRequest("/foo", connection); + var pollContext = MakeRequest("/foo", connection, services); var pollTask = dispatcher.ExecuteAsync(pollContext, options, app); // fail LongPollingTransport ReadAsync connection.Transport.Output.Complete(new InvalidOperationException()); @@ -2281,10 +2283,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -2332,10 +2334,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var connection = manager.CreateConnection(); connection.TransportType = HttpTransportType.ServerSentEvents; var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); - SetTransport(context, connection.TransportType); var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, connection.TransportType); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -2361,12 +2364,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests connection.TransportType = HttpTransportType.WebSockets; var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - - var context = MakeRequest("/foo", connection); - SetTransport(context, HttpTransportType.WebSockets); - var services = new ServiceCollection(); services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); + SetTransport(context, HttpTransportType.WebSockets); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -2411,13 +2413,13 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var connection = manager.CreateConnection(); connection.TransportType = HttpTransportType.ServerSentEvents; var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); - var context = MakeRequest("/foo", connection); + var services = new ServiceCollection(); + services.AddSingleton(); + var context = MakeRequest("/foo", connection, services); var lifetimeFeature = new CustomHttpRequestLifetimeFeature(); context.Features.Set(lifetimeFeature); SetTransport(context, connection.TransportType); - var services = new ServiceCollection(); - services.AddSingleton(); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); var app = builder.Build(); @@ -2436,6 +2438,149 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests } } + [Fact] + public async Task ServicesAvailableWithLongPolling() + { + using (StartVerifiableLog()) + { + var manager = CreateConnectionManager(LoggerFactory); + var connection = manager.CreateConnection(); + connection.TransportType = HttpTransportType.LongPolling; + + var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); + + var services = new ServiceCollection(); + services.AddSingleton(); + services.AddSingleton(new MessageWrapper() { Buffer = new ReadOnlySequence(new byte[] { 1, 2, 3 }) }); + var builder = new ConnectionBuilder(services.BuildServiceProvider()); + builder.UseConnectionHandler(); + var app = builder.Build(); + var options = new HttpConnectionDispatcherOptions(); + + var context = MakeRequest("/foo", connection, services); + + // Initial poll will complete immediately + await dispatcher.ExecuteAsync(context, options, app).OrTimeout(); + + var pollContext = MakeRequest("/foo", connection, services); + var pollTask = dispatcher.ExecuteAsync(pollContext, options, app); + + await connection.Application.Output.WriteAsync(new byte[] { 1 }).OrTimeout(); + await pollTask.OrTimeout(); + + var memory = new Memory(new byte[10]); + pollContext.Response.Body.Position = 0; + Assert.Equal(3, await pollContext.Response.Body.ReadAsync(memory).OrTimeout()); + Assert.Equal(new byte[] { 1, 2, 3 }, memory.Slice(0, 3).ToArray()); + + // Connection will use the original service provider so this will have no effect + services.AddSingleton(new MessageWrapper() { Buffer = new ReadOnlySequence(new byte[] { 4, 5, 6 }) }); + pollContext = MakeRequest("/foo", connection, services); + pollTask = dispatcher.ExecuteAsync(pollContext, options, app); + + await connection.Application.Output.WriteAsync(new byte[] { 1 }).OrTimeout(); + await pollTask.OrTimeout(); + + pollContext.Response.Body.Position = 0; + Assert.Equal(3, await pollContext.Response.Body.ReadAsync(memory).OrTimeout()); + Assert.Equal(new byte[] { 1, 2, 3 }, memory.Slice(0, 3).ToArray()); + + await connection.DisposeAsync().OrTimeout(); + } + } + + [Fact] + public async Task ServicesPreserveScopeWithLongPolling() + { + using (StartVerifiableLog()) + { + var manager = CreateConnectionManager(LoggerFactory); + var connection = manager.CreateConnection(); + connection.TransportType = HttpTransportType.LongPolling; + + var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); + + var services = new ServiceCollection(); + services.AddSingleton(); + var iteration = 0; + services.AddScoped(typeof(MessageWrapper), _ => + { + iteration++; + return new MessageWrapper() { Buffer = new ReadOnlySequence(new byte[] { (byte)(iteration + 1), (byte)(iteration + 2), (byte)(iteration + 3) }) }; + }); + + var builder = new ConnectionBuilder(services.BuildServiceProvider()); + builder.UseConnectionHandler(); + var app = builder.Build(); + var options = new HttpConnectionDispatcherOptions(); + + var context = MakeRequest("/foo", connection, services); + + // Initial poll will complete immediately + await dispatcher.ExecuteAsync(context, options, app).OrTimeout(); + + var pollContext = MakeRequest("/foo", connection, services); + var pollTask = dispatcher.ExecuteAsync(pollContext, options, app); + + await connection.Application.Output.WriteAsync(new byte[] { 1 }).OrTimeout(); + await pollTask.OrTimeout(); + + var memory = new Memory(new byte[10]); + pollContext.Response.Body.Position = 0; + Assert.Equal(3, await pollContext.Response.Body.ReadAsync(memory).OrTimeout()); + Assert.Equal(new byte[] { 2, 3, 4 }, memory.Slice(0, 3).ToArray()); + + pollContext = MakeRequest("/foo", connection, services); + pollTask = dispatcher.ExecuteAsync(pollContext, options, app); + + await connection.Application.Output.WriteAsync(new byte[] { 1 }).OrTimeout(); + await pollTask.OrTimeout(); + + pollContext.Response.Body.Position = 0; + Assert.Equal(3, await pollContext.Response.Body.ReadAsync(memory).OrTimeout()); + Assert.Equal(new byte[] { 2, 3, 4 }, memory.Slice(0, 3).ToArray()); + + await connection.DisposeAsync().OrTimeout(); + } + } + + [Fact] + public async Task DisposeLongPollingConnectionDisposesServiceScope() + { + using (StartVerifiableLog()) + { + var manager = CreateConnectionManager(LoggerFactory); + var connection = manager.CreateConnection(); + connection.TransportType = HttpTransportType.LongPolling; + + var dispatcher = new HttpConnectionDispatcher(manager, LoggerFactory); + + var services = new ServiceCollection(); + services.AddSingleton(); + var iteration = 0; + services.AddScoped(typeof(MessageWrapper), _ => + { + iteration++; + return new MessageWrapper() { Buffer = new ReadOnlySequence(new byte[] { (byte)(iteration + 1), (byte)(iteration + 2), (byte)(iteration + 3) }) }; + }); + + var builder = new ConnectionBuilder(services.BuildServiceProvider()); + builder.UseConnectionHandler(); + var app = builder.Build(); + var options = new HttpConnectionDispatcherOptions(); + + var context = MakeRequest("/foo", connection, services); + + // Initial poll will complete immediately + await dispatcher.ExecuteAsync(context, options, app).OrTimeout(); + + // ServiceScope will be disposed here + await connection.DisposeAsync().OrTimeout(); + + Assert.Throws(() => connection.ServiceScope.ServiceProvider.GetService()); + } + } + private static async Task CheckTransportSupported(HttpTransportType supportedTransports, HttpTransportType transportType, int status, ILoggerFactory loggerFactory) { var manager = CreateConnectionManager(loggerFactory); @@ -2459,6 +2604,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests values["negotiateVersion"] = "1"; var qs = new QueryCollection(values); context.Request.Query = qs; + context.RequestServices = services.BuildServiceProvider(); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler(); @@ -2478,7 +2624,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests } } - private static DefaultHttpContext MakeRequest(string path, HttpConnectionContext connection, string format = null) + private static DefaultHttpContext MakeRequest(string path, HttpConnectionContext connection, IServiceCollection serviceCollection, string format = null) { var context = new DefaultHttpContext(); context.Features.Set(new ResponseFeature()); @@ -2494,6 +2640,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests var qs = new QueryCollection(values); context.Request.Query = qs; context.Response.Body = new MemoryStream(); + context.RequestServices = serviceCollection.BuildServiceProvider(); return context; } @@ -2632,6 +2779,35 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests } } + public class ServiceProviderConnectionHandler : ConnectionHandler + { + public override async Task OnConnectedAsync(ConnectionContext connection) + { + while (true) + { + var result = await connection.Transport.Input.ReadAsync(); + + try + { + if (result.IsCompleted) + { + break; + } + + var context = connection.GetHttpContext(); + var message = context.RequestServices.GetService(); + + // Echo the results + await connection.Transport.Output.WriteAsync(message.Buffer.ToArray()); + } + finally + { + connection.Transport.Input.AdvanceTo(result.Buffer.End); + } + } + } + } + public class ResponseFeature : HttpResponseFeature { public override void OnCompleted(Func callback, object state) @@ -2642,4 +2818,9 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests { } } + + public class MessageWrapper + { + public ReadOnlySequence Buffer { get; set; } + } } From cd9da1c3503d89e7f42b7ee780416eb1d4036b84 Mon Sep 17 00:00:00 2001 From: William Godbe Date: Wed, 24 Jun 2020 12:59:33 -0700 Subject: [PATCH 023/100] Fixup kestrel config tests after feedback (#23308) --- src/Servers/Kestrel/Kestrel/test/ConfigurationReaderTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Servers/Kestrel/Kestrel/test/ConfigurationReaderTests.cs b/src/Servers/Kestrel/Kestrel/test/ConfigurationReaderTests.cs index 3328b08ce2..06345cc462 100644 --- a/src/Servers/Kestrel/Kestrel/test/ConfigurationReaderTests.cs +++ b/src/Servers/Kestrel/Kestrel/test/ConfigurationReaderTests.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Security.Authentication; +using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal; using Microsoft.Extensions.Configuration; using Xunit; @@ -74,7 +75,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests var config = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Certificates:filecert:Path", "/path/cert.pfx"), - new KeyValuePair("Certificates:FILECERT:Password", "certpassword"), + new KeyValuePair("CERTIFICATES:FILECERT:PASSWORD", "certpassword"), }).Build(); var reader = new ConfigurationReader(config); var certificates = reader.Certificates; @@ -98,7 +99,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests new KeyValuePair("Certificates:FILECERT:Password", "certpassword"), }).Build()); - Assert.Contains("An item with the same key has already been added", exception.Message); + Assert.Contains(CoreStrings.KeyAlreadyExists, exception.Message); } [Fact] From c19f3d29ca8fd1b8359940b52faf4c32d2b0b601 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Wed, 24 Jun 2020 23:48:36 +0100 Subject: [PATCH 024/100] Only look-up Cache-Control once (#23329) Only look-up the Cache-Control header once, rather than twice if non-empty. --- .../ResponseCaching/src/ResponseCachingPolicyProvider.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Middleware/ResponseCaching/src/ResponseCachingPolicyProvider.cs b/src/Middleware/ResponseCaching/src/ResponseCachingPolicyProvider.cs index 3cb94ab005..491d803d94 100644 --- a/src/Middleware/ResponseCaching/src/ResponseCachingPolicyProvider.cs +++ b/src/Middleware/ResponseCaching/src/ResponseCachingPolicyProvider.cs @@ -34,11 +34,12 @@ namespace Microsoft.AspNetCore.ResponseCaching public virtual bool AllowCacheLookup(ResponseCachingContext context) { var requestHeaders = context.HttpContext.Request.Headers; + var cacheControl = requestHeaders[HeaderNames.CacheControl]; // Verify request cache-control parameters - if (!StringValues.IsNullOrEmpty(requestHeaders[HeaderNames.CacheControl])) + if (!StringValues.IsNullOrEmpty(cacheControl)) { - if (HeaderUtilities.ContainsCacheDirective(requestHeaders[HeaderNames.CacheControl], CacheControlHeaderValue.NoCacheString)) + if (HeaderUtilities.ContainsCacheDirective(cacheControl, CacheControlHeaderValue.NoCacheString)) { context.Logger.RequestWithNoCacheNotCacheable(); return false; From ac291877c73e27af81e212633c458003c421fd7b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 24 Jun 2020 16:58:18 -0700 Subject: [PATCH 025/100] Remove WebAssemblyHttpHandler ref-assembly package (#23245) * Remove WebAssemblyHttpHandler ref-assembly package Fixes https://github.com/dotnet/aspnetcore/issues/22283 * Fixup --- eng/ProjectReferences.props | 1 - src/Components/Components.sln | 15 ------------- src/Components/ComponentsNoDeps.slnf | 1 - src/Components/Directory.Build.targets | 22 ------------------- ...t.AspNetCore.Components.WebAssembly.csproj | 5 ----- ....Components.WebAssembly.HttpHandler.csproj | 16 -------------- ....WebAssembly.HttpHandler.netstandard2.1.cs | 11 ---------- ....Components.WebAssembly.HttpHandler.nuspec | 13 ----------- .../HostedInAspNet.Client.csproj | 2 -- .../Wasm.Authentication.Client.csproj | 2 -- .../BasicTestApp/BasicTestApp.csproj | 2 -- 11 files changed, 90 deletions(-) delete mode 100644 src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj delete mode 100644 src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.netstandard2.1.cs delete mode 100644 src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.nuspec diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index dd12efa35e..91343d8b13 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -67,7 +67,6 @@ - diff --git a/src/Components/Components.sln b/src/Components/Components.sln index 722c3a4ea1..cfdbc2bce2 100644 --- a/src/Components/Components.sln +++ b/src/Components/Components.sln @@ -257,8 +257,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication", "Authentication", "{81250121-9B43-40B1-BF11-CE4458F2676C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.HttpHandler", "WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj", "{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Client", "WebAssembly\testassets\Wasm.Authentication.Client\Wasm.Authentication.Client.csproj", "{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Shared", "WebAssembly\testassets\Wasm.Authentication.Shared\Wasm.Authentication.Shared.csproj", "{630D5388-7A2F-42DD-9154-1F62A18CBB69}" @@ -1523,18 +1521,6 @@ Global {6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x64.Build.0 = Release|Any CPU {6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x86.ActiveCfg = Release|Any CPU {6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x86.Build.0 = Release|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x64.ActiveCfg = Debug|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x64.Build.0 = Debug|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x86.ActiveCfg = Debug|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x86.Build.0 = Debug|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|Any CPU.Build.0 = Release|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x64.ActiveCfg = Release|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x64.Build.0 = Release|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x86.ActiveCfg = Release|Any CPU - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x86.Build.0 = Release|Any CPU {5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.Build.0 = Debug|Any CPU {5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -1687,7 +1673,6 @@ Global {5CD61479-5181-4A5B-B90F-9F34316248B3} = {81250121-9B43-40B1-BF11-CE4458F2676C} {6B0D6C08-FC30-4822-9464-4D24FF4CDC17} = {81250121-9B43-40B1-BF11-CE4458F2676C} {81250121-9B43-40B1-BF11-CE4458F2676C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} - {031AD67E-DDDE-4A20-874A-8D0A791C6F4C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF} {5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10} {630D5388-7A2F-42DD-9154-1F62A18CBB69} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10} {A062ACCE-AB0D-4569-9548-4BC0D9A9174B} = {2FC10057-7A0A-4E34-8302-879925BC0102} diff --git a/src/Components/ComponentsNoDeps.slnf b/src/Components/ComponentsNoDeps.slnf index 0484ef907c..a73ab83b19 100644 --- a/src/Components/ComponentsNoDeps.slnf +++ b/src/Components/ComponentsNoDeps.slnf @@ -24,7 +24,6 @@ "WebAssembly\\Server\\test\\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj", "WebAssembly\\WebAssembly.Authentication\\src\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj", "WebAssembly\\WebAssembly.Authentication\\test\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests.csproj", - "WebAssembly\\WebAssemblyHttpHandler\\src\\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj", "WebAssembly\\WebAssembly\\src\\Microsoft.AspNetCore.Components.WebAssembly.csproj", "WebAssembly\\WebAssembly\\test\\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj", "WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj", diff --git a/src/Components/Directory.Build.targets b/src/Components/Directory.Build.targets index 1ecdb38eaf..69204d61a6 100644 --- a/src/Components/Directory.Build.targets +++ b/src/Components/Directory.Build.targets @@ -21,26 +21,4 @@ - - - - - - - - - <_HttpHandlerAssembly Include="@(_BlazorUserRuntimeAssembly)" - Condition="%(_BlazorUserRuntimeAssembly.ProjectReferenceOriginalItemSpec) == '$(RepoRoot)src\Components\WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj'" /> - - <_BlazorUserRuntimeAssembly Remove="@(_HttpHandlerAssembly)" /> - - diff --git a/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj b/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj index 2aab0dbca7..226f0d77e9 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj +++ b/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj @@ -23,11 +23,6 @@ Private="false" Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" /> - - - diff --git a/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj b/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj deleted file mode 100644 index d8417f63b3..0000000000 --- a/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - $(MSBuildProjectName).nuspec - netstandard2.1 - $(MSBuildProjectName) - System.Net.Http.WebAssemblyHttpHandler - 0.2.2.0 - true - Open - - - - - - - diff --git a/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.netstandard2.1.cs b/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.netstandard2.1.cs deleted file mode 100644 index 0d0dbc1f75..0000000000 --- a/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.netstandard2.1.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Net.Http; - -namespace System.Net.Http -{ - public partial class WebAssemblyHttpHandler : System.Net.Http.HttpMessageHandler - { - public WebAssemblyHttpHandler() { } - protected override System.Threading.Tasks.Task SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { throw null; } - } -} diff --git a/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.nuspec b/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.nuspec deleted file mode 100644 index fd5ccf21a0..0000000000 --- a/src/Components/WebAssembly/WebAssemblyHttpHandler/src/Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.nuspec +++ /dev/null @@ -1,13 +0,0 @@ - - - - $CommonMetadataElements$ - - - - - - $CommonFileElements$ - - - diff --git a/src/Components/WebAssembly/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj b/src/Components/WebAssembly/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj index 4994c3eb7d..0ff01b2ab1 100644 --- a/src/Components/WebAssembly/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj +++ b/src/Components/WebAssembly/testassets/HostedInAspNet.Client/HostedInAspNet.Client.csproj @@ -4,8 +4,6 @@ $(DefaultNetCoreTargetFramework) browser-wasm true - - true diff --git a/src/Components/WebAssembly/testassets/Wasm.Authentication.Client/Wasm.Authentication.Client.csproj b/src/Components/WebAssembly/testassets/Wasm.Authentication.Client/Wasm.Authentication.Client.csproj index 16fddd3ddc..484aa06fce 100644 --- a/src/Components/WebAssembly/testassets/Wasm.Authentication.Client/Wasm.Authentication.Client.csproj +++ b/src/Components/WebAssembly/testassets/Wasm.Authentication.Client/Wasm.Authentication.Client.csproj @@ -4,8 +4,6 @@ $(DefaultNetCoreTargetFramework) browser-wasm true - - true diff --git a/src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj b/src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj index 3923c0d5c0..f47ac9084a 100644 --- a/src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj +++ b/src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj @@ -10,8 +10,6 @@ false - - true From a90f4421ee019b7e274e7bb38b0b128a84e62d68 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2020 00:52:55 +0000 Subject: [PATCH 026/100] Update dependencies from https://github.com/dotnet/efcore build 20200624.1 (#23337) Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20323.10 -> To Version 5.0.0-preview.8.20324.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 33397e6ac9..23bd9613e7 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 8cd69e0dc91fef323535794fff7873c67dcabe8e + 4ce52b6f0e654f2f5c7ca1fdce8b4badc6907522 - + https://github.com/dotnet/efcore - 8cd69e0dc91fef323535794fff7873c67dcabe8e + 4ce52b6f0e654f2f5c7ca1fdce8b4badc6907522 - + https://github.com/dotnet/efcore - 8cd69e0dc91fef323535794fff7873c67dcabe8e + 4ce52b6f0e654f2f5c7ca1fdce8b4badc6907522 - + https://github.com/dotnet/efcore - 8cd69e0dc91fef323535794fff7873c67dcabe8e + 4ce52b6f0e654f2f5c7ca1fdce8b4badc6907522 - + https://github.com/dotnet/efcore - 8cd69e0dc91fef323535794fff7873c67dcabe8e + 4ce52b6f0e654f2f5c7ca1fdce8b4badc6907522 - + https://github.com/dotnet/efcore - 8cd69e0dc91fef323535794fff7873c67dcabe8e + 4ce52b6f0e654f2f5c7ca1fdce8b4badc6907522 - + https://github.com/dotnet/efcore - 8cd69e0dc91fef323535794fff7873c67dcabe8e + 4ce52b6f0e654f2f5c7ca1fdce8b4badc6907522 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 311aa670d5..90cc76fa95 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.8.20323.10 - 5.0.0-preview.8.20323.10 - 5.0.0-preview.8.20323.10 - 5.0.0-preview.8.20323.10 - 5.0.0-preview.8.20323.10 - 5.0.0-preview.8.20323.10 - 5.0.0-preview.8.20323.10 + 5.0.0-preview.8.20324.1 + 5.0.0-preview.8.20324.1 + 5.0.0-preview.8.20324.1 + 5.0.0-preview.8.20324.1 + 5.0.0-preview.8.20324.1 + 5.0.0-preview.8.20324.1 + 5.0.0-preview.8.20324.1 - + https://github.com/dotnet/runtime - d908270add914db0e9fb3ce72e93c410e8f0f95a + 4a21529178750aab4b194d54918d0676e0e5833a - + https://github.com/dotnet/runtime - d908270add914db0e9fb3ce72e93c410e8f0f95a + 4a21529178750aab4b194d54918d0676e0e5833a - + https://github.com/dotnet/runtime - d908270add914db0e9fb3ce72e93c410e8f0f95a + 4a21529178750aab4b194d54918d0676e0e5833a https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index 90cc76fa95..b78104f650 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,79 +66,79 @@ 3.7.0-4.20319.6 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 - 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20323.9 + 5.0.0-preview.8.20325.1 3.2.0 - 5.0.0-preview.8.20324.1 - 5.0.0-preview.8.20324.1 - 5.0.0-preview.8.20324.1 - 5.0.0-preview.8.20324.1 - 5.0.0-preview.8.20324.1 - 5.0.0-preview.8.20324.1 - 5.0.0-preview.8.20324.1 + 5.0.0-preview.8.20324.2 + 5.0.0-preview.8.20324.2 + 5.0.0-preview.8.20324.2 + 5.0.0-preview.8.20324.2 + 5.0.0-preview.8.20324.2 + 5.0.0-preview.8.20324.2 + 5.0.0-preview.8.20324.2 3.2.0 - 5.0.0-preview.8.20324.2 - 5.0.0-preview.8.20324.2 - 5.0.0-preview.8.20324.2 - 5.0.0-preview.8.20324.2 - 5.0.0-preview.8.20324.2 - 5.0.0-preview.8.20324.2 - 5.0.0-preview.8.20324.2 + 5.0.0-preview.8.20325.4 + 5.0.0-preview.8.20325.4 + 5.0.0-preview.8.20325.4 + 5.0.0-preview.8.20325.4 + 5.0.0-preview.8.20325.4 + 5.0.0-preview.8.20325.4 + 5.0.0-preview.8.20325.4 - + https://github.com/dotnet/runtime - 4a21529178750aab4b194d54918d0676e0e5833a + c84811a7c87b1c58e63d572778124742d5c853bb - + https://github.com/dotnet/runtime - 4a21529178750aab4b194d54918d0676e0e5833a + c84811a7c87b1c58e63d572778124742d5c853bb - + https://github.com/dotnet/runtime - 4a21529178750aab4b194d54918d0676e0e5833a + c84811a7c87b1c58e63d572778124742d5c853bb https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index f17e8569aa..fed8b53901 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,69 +66,69 @@ 3.7.0-4.20319.6 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 - 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20325.1 + 5.0.0-preview.8.20326.2 3.2.0 From e4158e8a5946c859e849e42a75bc86619c49ab5e Mon Sep 17 00:00:00 2001 From: Brennan Date: Fri, 26 Jun 2020 15:42:48 -0700 Subject: [PATCH 040/100] Quarantine Publish_HostedApp_VisualStudio_WithSatelliteAssemblies and Publish_UpdatesFilesWhenSourcesChange (#23398) * Update WasmPublishIntegrationTest.cs * Update WasmCompressionTests.cs --- .../integrationtests/Wasm/WasmCompressionTests.cs | 2 ++ .../integrationtests/Wasm/WasmPublishIntegrationTest.cs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmCompressionTests.cs b/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmCompressionTests.cs index e308d78274..d4e375b0b0 100644 --- a/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmCompressionTests.cs +++ b/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmCompressionTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Xunit; namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests @@ -10,6 +11,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests public class WasmCompressionTests { [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23397")] public async Task Publish_UpdatesFilesWhenSourcesChange() { // Arrange diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmPublishIntegrationTest.cs b/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmPublishIntegrationTest.cs index dfaec7c803..6ce305d136 100644 --- a/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmPublishIntegrationTest.cs +++ b/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmPublishIntegrationTest.cs @@ -531,6 +531,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests // Regression test to verify satellite assemblies from the blazor app are copied to the published app's wwwroot output directory as // part of publishing in VS [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23397")] public async Task Publish_HostedApp_VisualStudio_WithSatelliteAssemblies() { // Simulates publishing the same way VS does by setting BuildProjectReferences=false. From 93eafe70b437ffe8a00fc6f18c67459e26b09b18 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Fri, 26 Jun 2020 16:26:54 -0700 Subject: [PATCH 041/100] Run full matrix on quarantined pipeline (#23377) * Run full matrix on quarantined pipeline but only 2x a day * Add helix arm queues * Change test run time * Update quarantined-tests.yml --- .azure/pipelines/quarantined-tests.yml | 41 +++++++++++++++++++------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/.azure/pipelines/quarantined-tests.yml b/.azure/pipelines/quarantined-tests.yml index b26f0194ca..6f9aa3ab89 100644 --- a/.azure/pipelines/quarantined-tests.yml +++ b/.azure/pipelines/quarantined-tests.yml @@ -1,13 +1,10 @@ -# We want to run quarantined tests on master as well as on PRs -trigger: - batch: true - branches: - include: - - master +# We only want to run quarantined tests on master +pr: none +trigger: none schedules: -- cron: "0 */4 * * *" - displayName: Every 4 hours test run +- cron: "0 18 * * *" + displayName: Run tests once a day at 11 PM branches: include: - master @@ -28,7 +25,7 @@ jobs: jobName: Helix_quarantined_x64 jobDisplayName: 'Tests: Helix' agentOs: Windows - timeoutInMinutes: 180 + timeoutInMinutes: 480 steps: # Build the shared framework - script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log @@ -36,7 +33,7 @@ jobs: - script: ./build.cmd -ci -nobl -noBuildRepoTasks -restore -noBuild -noBuildNative -projects src/Grpc/**/*.csproj displayName: Restore interop projects - script: ./build.cmd -ci -nobl -noBuildRepoTasks -noRestore -test -all -noBuildJava -noBuildNative - -projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true + -projects eng\helix\helix.proj /p:IsHelixDaily=true /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildInteropProjects=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log displayName: Run build.cmd helix target continueOnError: true @@ -48,6 +45,30 @@ jobs: path: artifacts/log/ publishOnError: true +# Helix ARM64 +- template: jobs/default-build.yml + parameters: + jobName: Helix_quarantined_arm64 + jobDisplayName: "Tests: Helix ARM64" + agentOs: Linux + timeoutInMinutes: 480 + steps: + - script: ./restore.sh -ci -nobl + displayName: Restore + - script: ./build.sh --ci --nobl --noBuildRepoTasks --arch arm64 -test --no-build-nodejs --all --projects + $(Build.SourcesDirectory)/eng/helix/helix.proj /p:IsHelixJob=true /p:IsHelixDaily=true /p:RunQuarantinedTests=true + /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log + displayName: Run build.sh helix arm64 target + env: + HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues + SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops + installNodeJs: false + artifacts: + - name: Helix_arm64_logs + path: artifacts/log/ + publishOnError: true + includeForks: true + - template: jobs/default-build.yml parameters: jobName: Windows_Quarantined_x64 From 73555970ee960f56e361b5858ac92733b73185b1 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Fri, 26 Jun 2020 18:16:29 -0700 Subject: [PATCH 042/100] Quarantine dotnet-watch test (#23395) * Quarantine dotnet-watch test * Update ProgramTests.cs --- src/Tools/dotnet-watch/test/ProgramTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tools/dotnet-watch/test/ProgramTests.cs b/src/Tools/dotnet-watch/test/ProgramTests.cs index 9aa2f540cc..8d7557853d 100644 --- a/src/Tools/dotnet-watch/test/ProgramTests.cs +++ b/src/Tools/dotnet-watch/test/ProgramTests.cs @@ -24,6 +24,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23394")] // Failure on OSX https://dev.azure.com/dnceng/public/_build/results?buildId=706059&view=ms.vss-test-web.build-test-results-tab public async Task ConsoleCancelKey() { _tempDir From 646de19f1da5a88c7cc8d01fc3afe7dc3cdfb917 Mon Sep 17 00:00:00 2001 From: Brennan Date: Fri, 26 Jun 2020 21:33:29 -0700 Subject: [PATCH 043/100] Update HubProtocol.md (#23389) --- src/SignalR/docs/specs/HubProtocol.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SignalR/docs/specs/HubProtocol.md b/src/SignalR/docs/specs/HubProtocol.md index d8c4ce8938..ed7a1aa832 100644 --- a/src/SignalR/docs/specs/HubProtocol.md +++ b/src/SignalR/docs/specs/HubProtocol.md @@ -543,7 +543,7 @@ MessagePack uses different formats to encode values. Refer to the [MsgPack forma `Invocation` messages have the following structure: ``` -[1, Headers, InvocationId, NonBlocking, Target, [Arguments], [StreamIds]] +[1, Headers, InvocationId, Target, [Arguments], [StreamIds]] ``` * `1` - Message Type - `1` indicates this is an `Invocation` message. From a07449123a2eaea5237a060f08dc50a39dcb8715 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 27 Jun 2020 06:44:36 +0000 Subject: [PATCH 044/100] Update dependencies from https://github.com/dotnet/efcore build 20200626.2 (#23429) Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20325.4 -> To Version 5.0.0-preview.8.20326.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 30 +++++++++++++++--------------- eng/Versions.props | 16 ++++++++-------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 394019011c..ccd90e69bd 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 3e5ee6c5deb9ad147058c5f9fa4c21a638306840 + d617979226ed173999292195574a87f7074f5be4 - + https://github.com/dotnet/efcore - 3e5ee6c5deb9ad147058c5f9fa4c21a638306840 + d617979226ed173999292195574a87f7074f5be4 - + https://github.com/dotnet/efcore - 3e5ee6c5deb9ad147058c5f9fa4c21a638306840 + d617979226ed173999292195574a87f7074f5be4 - + https://github.com/dotnet/efcore - 3e5ee6c5deb9ad147058c5f9fa4c21a638306840 + d617979226ed173999292195574a87f7074f5be4 - + https://github.com/dotnet/efcore - 3e5ee6c5deb9ad147058c5f9fa4c21a638306840 + d617979226ed173999292195574a87f7074f5be4 - + https://github.com/dotnet/efcore - 3e5ee6c5deb9ad147058c5f9fa4c21a638306840 + d617979226ed173999292195574a87f7074f5be4 - + https://github.com/dotnet/efcore - 3e5ee6c5deb9ad147058c5f9fa4c21a638306840 + d617979226ed173999292195574a87f7074f5be4 https://github.com/dotnet/runtime @@ -313,4 +313,4 @@ 5911981d56de6afdaa84b26343ab915c5f9aca56 - \ No newline at end of file + diff --git a/eng/Versions.props b/eng/Versions.props index 5b021acca9..8c2559e734 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.8.20325.4 - 5.0.0-preview.8.20325.4 - 5.0.0-preview.8.20325.4 - 5.0.0-preview.8.20325.4 - 5.0.0-preview.8.20325.4 - 5.0.0-preview.8.20325.4 - 5.0.0-preview.8.20325.4 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20326.2 - + https://github.com/dotnet/runtime - c84811a7c87b1c58e63d572778124742d5c853bb + 0f7b3532e573b72f9d3eb9161513d8405be24d6f - + https://github.com/dotnet/runtime - c84811a7c87b1c58e63d572778124742d5c853bb + 0f7b3532e573b72f9d3eb9161513d8405be24d6f - + https://github.com/dotnet/runtime - c84811a7c87b1c58e63d572778124742d5c853bb + 0f7b3532e573b72f9d3eb9161513d8405be24d6f https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index 8c2559e734..f4216fe7dc 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,79 +66,79 @@ 3.7.0-4.20319.6 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20328.1 3.2.0 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 - 5.0.0-preview.8.20326.2 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.1 - + https://github.com/dotnet/runtime - 0f7b3532e573b72f9d3eb9161513d8405be24d6f + 98b6284e020845c04bc7b1cefdcd01ffe7a4a8c0 - + https://github.com/dotnet/runtime - 0f7b3532e573b72f9d3eb9161513d8405be24d6f + 98b6284e020845c04bc7b1cefdcd01ffe7a4a8c0 - + https://github.com/dotnet/runtime - 0f7b3532e573b72f9d3eb9161513d8405be24d6f + 98b6284e020845c04bc7b1cefdcd01ffe7a4a8c0 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index f4216fe7dc..b00ca00d91 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,69 +66,69 @@ 3.7.0-4.20319.6 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20328.6 3.2.0 From e280884a94e5349bafebfed2073b1cd00d0ce1ad Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Mon, 29 Jun 2020 11:18:04 -0700 Subject: [PATCH 051/100] Create a new pipeline that runs PR queue tests more often (#23410) --- .azure/pipelines/quarantined-pr.yml | 149 ++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 .azure/pipelines/quarantined-pr.yml diff --git a/.azure/pipelines/quarantined-pr.yml b/.azure/pipelines/quarantined-pr.yml new file mode 100644 index 0000000000..d6e4b61ed2 --- /dev/null +++ b/.azure/pipelines/quarantined-pr.yml @@ -0,0 +1,149 @@ +# We want to run quarantined tests on master as well as on PRs +trigger: + batch: true + branches: + include: + - master + +schedules: +- cron: "0 */4 * * *" + displayName: Every 4 hours test run + branches: + include: + - master + always: true + +variables: +- ${{ if ne(variables['System.TeamProject'], 'internal') }}: + - name: _UseHelixOpenQueues + value: 'true' +- ${{ if eq(variables['System.TeamProject'], 'internal') }}: + - group: DotNet-HelixApi-Access + - name: _UseHelixOpenQueues + value: 'false' + +jobs: +- template: jobs/default-build.yml + parameters: + jobName: Helix_quarantined_x64 + jobDisplayName: 'Tests: Helix' + agentOs: Windows + timeoutInMinutes: 240 + steps: + # Build the shared framework + - script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log + displayName: Build shared fx + - script: ./build.cmd -ci -nobl -noBuildRepoTasks -restore -noBuild -noBuildNative -projects src/Grpc/**/*.csproj + displayName: Restore interop projects + - script: ./build.cmd -ci -nobl -noBuildRepoTasks -noRestore -test -all -noBuildJava -noBuildNative + -projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true + /p:BuildInteropProjects=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log + displayName: Run build.cmd helix target + continueOnError: true + env: + HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues + SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops + artifacts: + - name: Helix_logs + path: artifacts/log/ + publishOnError: true + +- template: jobs/default-build.yml + parameters: + jobName: Windows_Quarantined_x64 + jobDisplayName: 'Tests: Windows x64' + agentOs: Windows + timeoutInMinutes: 240 + isTestingJob: true + steps: + - powershell: "& ./build.ps1 -CI -nobl -all -pack -NoBuildJava" + displayName: Build + # The templates part can be removed when the Blazor Templates run on Helix + - script: ./src/ProjectTemplates/build.cmd -ci -nobl -pack -NoRestore -NoBuilddeps "/p:RunTemplateTests=true" + displayName: Pack Templates + - script: ./build.cmd -ci -nobl -test -NoRestore -NoBuild -NoBuilddeps "/p:RunTemplateTests=true /p:RunQuarantinedTests=true /p:SkipHelixReadyTests=true" + displayName: Run Quarantined Tests + continueOnError: true + - task: PublishTestResults@2 + displayName: Publish Quarantined Test Results + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined' + condition: always() + artifacts: + - name: Windows_Quarantined_Test_Logs + path: artifacts/log/ + publishOnError: true + includeForks: true + - name: Windows_Quarantined_Test_Results + path: artifacts/TestResults/ + publishOnError: true + includeForks: true + +- template: jobs/default-build.yml + parameters: + jobName: MacOS_Quarantined_Test + jobDisplayName: "Tests: macOS 10.14" + agentOs: macOS + timeoutInMinutes: 240 + isTestingJob: true + steps: + - bash: ./build.sh --all --pack --ci --nobl --no-build-java + displayName: Build + # The templates part can be removed when the Blazor Templates run on Helix + - bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps + displayName: Pack Templates (for Template tests) + - bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true + displayName: Run Quarantined Tests + continueOnError: true + - task: PublishTestResults@2 + displayName: Publish Quarantined Test Results + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined' + condition: always() + artifacts: + - name: MacOS_Quarantined_Test_Logs + path: artifacts/log/ + publishOnError: true + includeForks: true + - name: MacOS_Quarantined_Test_Results + path: artifacts/TestResults/ + publishOnError: true + includeForks: true + +- template: jobs/default-build.yml + parameters: + jobName: Linux_Quarantined_Test + jobDisplayName: "Tests: Ubuntu 16.04 x64" + agentOs: Linux + timeoutInMinutes: 240 + isTestingJob: true + useHostedUbuntu: false + steps: + - bash: ./build.sh --all --pack --ci --nobl --no-build-java + displayName: Build + # The templates part can be removed when the Blazor Templates run on Helix + - bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps + displayName: Pack Templates (for Template tests) + - bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true + displayName: Run Quarantined Tests + continueOnError: true + - task: PublishTestResults@2 + displayName: Publish Quarantined Test Results + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined' + condition: always() + artifacts: + - name: Linux_Quarantined_Test_Logs + path: artifacts/log/ + publishOnError: true + includeForks: true + - name: Linux_Quarantined_Test_Results + path: artifacts/TestResults/ + publishOnError: true + includeForks: true From e906c2067be5552bf15f0bd2a9c793a6ad4d3dc6 Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Mon, 29 Jun 2020 12:34:09 -0700 Subject: [PATCH 052/100] Quarantine Publish_HostedApp_WithSatelliteAssemblies (#23479) --- .../integrationtests/Wasm/WasmPublishIntegrationTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmPublishIntegrationTest.cs b/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmPublishIntegrationTest.cs index 6ce305d136..0404757fcf 100644 --- a/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmPublishIntegrationTest.cs +++ b/src/Razor/Microsoft.NET.Sdk.Razor/integrationtests/Wasm/WasmPublishIntegrationTest.cs @@ -344,6 +344,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23397")] public async Task Publish_HostedApp_WithSatelliteAssemblies() { // Arrange From 1c439be48b109e428589384bbb4b0633c2de1429 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Mon, 29 Jun 2020 14:27:51 -0700 Subject: [PATCH 053/100] Update Helix.md with additional guidance about queues/checkin expectations (#23486) --- docs/Helix.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/Helix.md b/docs/Helix.md index e8c733d5a8..318a9ef8cb 100644 --- a/docs/Helix.md +++ b/docs/Helix.md @@ -20,12 +20,23 @@ This will restore, and then publish all the test project including some bootstra - Required queues: Windows10, OSX, Ubuntu1604 - Full queue matrix: Windows[7, 81, 10], Ubuntu[1604, 1804, 2004], Centos7, Debian[8,9], Redhat7, Fedora28, Arm64 (Win10, Debian9) +- The queues are defined in [Helix.Common.props](https://github.com/dotnet/aspnetcore/blob/master/eng/targets/Helix.Common.props) -aspnetcore-ci runs non quarantined tests against the required helix queues as a required PR check and all builds on all branches. +[aspnetcore-ci](https://dev.azure.com/dnceng/public/_build?definitionId=278) runs non quarantined tests against the required helix queues as a required PR check and all builds on all branches. -aspnetcore-quarantined-tests runs only quarantined tests against the required queues only on master every 4 hours. +[aspnetcore-helix-matrix](https://dev.azure.com/dnceng/public/_build?definitionId=837) runs non quarantined tests against all queues twice a day only on public master. + +[aspnetcore-quarantined-pr](https://dev.azure.com/dnceng/public/_build?definitionId=869) runs only quarantined tests against the required queues on PRs and on master every 4 hours. + +[aspnetcore-quarantined-tests](https://dev.azure.com/dnceng/public/_build?definitionId=331) runs only quarantined tests against all queues only on public master once a day at 11 PM. + +You can always manually queue pipeline runs by clicking on the link to the pipeline -> Run Pipeline -> select your branch/tag and commit + +## Checkin process expectations + +- The normal PR process has aspnetcore-ci will ensure that the required queues are green. +- If your changes are likely to have cross platform impact that would affect more than the required queues, you should kick off a manual aspnetcore-helix-matrix pipeline run against your branch before merging your PR. Even though aspnetcore-helix-matrix is not a required checkin gate, if your changes break this pipeline, you must either immediately revert your changes, or quarantine the test, its never ok to leave this pipeline in a broken state. -aspnetcore-helix-matrix runs non quarantined tests against all queues twice a day only on public master. ## How do I look at the results of a helix run on Azure Pipelines? From 5eef64aed85e0f1dc72c5a3378422179f61dc6c7 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Mon, 29 Jun 2020 15:06:24 -0700 Subject: [PATCH 054/100] Remove duplicate non helix jobs from PR pipeline (#23481) --- .azure/pipelines/quarantined-tests.yml | 100 ------------------------- 1 file changed, 100 deletions(-) diff --git a/.azure/pipelines/quarantined-tests.yml b/.azure/pipelines/quarantined-tests.yml index 6f9aa3ab89..30fa8cbeb9 100644 --- a/.azure/pipelines/quarantined-tests.yml +++ b/.azure/pipelines/quarantined-tests.yml @@ -68,103 +68,3 @@ jobs: path: artifacts/log/ publishOnError: true includeForks: true - -- template: jobs/default-build.yml - parameters: - jobName: Windows_Quarantined_x64 - jobDisplayName: 'Tests: Windows x64' - agentOs: Windows - timeoutInMinutes: 180 - isTestingJob: true - steps: - - powershell: "& ./build.ps1 -CI -nobl -all -pack -NoBuildJava" - displayName: Build - # The templates part can be removed when the Blazor Templates run on Helix - - script: ./src/ProjectTemplates/build.cmd -ci -nobl -pack -NoRestore -NoBuilddeps "/p:RunTemplateTests=true" - displayName: Pack Templates - - script: ./build.cmd -ci -nobl -test -NoRestore -NoBuild -NoBuilddeps "/p:RunTemplateTests=true /p:RunQuarantinedTests=true /p:SkipHelixReadyTests=true" - displayName: Run Quarantined Tests - continueOnError: true - - task: PublishTestResults@2 - displayName: Publish Quarantined Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined' - condition: always() - artifacts: - - name: Windows_Quarantined_Test_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: Windows_Quarantined_Test_Results - path: artifacts/TestResults/ - publishOnError: true - includeForks: true - -- template: jobs/default-build.yml - parameters: - jobName: MacOS_Quarantined_Test - jobDisplayName: "Tests: macOS 10.14" - agentOs: macOS - timeoutInMinutes: 180 - isTestingJob: true - steps: - - bash: ./build.sh --all --pack --ci --nobl --no-build-java - displayName: Build - # The templates part can be removed when the Blazor Templates run on Helix - - bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps - displayName: Pack Templates (for Template tests) - - bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true - displayName: Run Quarantined Tests - continueOnError: true - - task: PublishTestResults@2 - displayName: Publish Quarantined Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined' - condition: always() - artifacts: - - name: MacOS_Quarantined_Test_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: MacOS_Quarantined_Test_Results - path: artifacts/TestResults/ - publishOnError: true - includeForks: true - -- template: jobs/default-build.yml - parameters: - jobName: Linux_Quarantined_Test - jobDisplayName: "Tests: Ubuntu 16.04 x64" - agentOs: Linux - timeoutInMinutes: 180 - isTestingJob: true - useHostedUbuntu: false - steps: - - bash: ./build.sh --all --pack --ci --nobl --no-build-java - displayName: Build - # The templates part can be removed when the Blazor Templates run on Helix - - bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps - displayName: Pack Templates (for Template tests) - - bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true - displayName: Run Quarantined Tests - continueOnError: true - - task: PublishTestResults@2 - displayName: Publish Quarantined Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined' - condition: always() - artifacts: - - name: Linux_Quarantined_Test_Logs - path: artifacts/log/ - publishOnError: true - includeForks: true - - name: Linux_Quarantined_Test_Results - path: artifacts/TestResults/ - publishOnError: true - includeForks: true From 76aef6aadfc5a8ab4d4fa5440f3e5c3f866c5221 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2020 23:03:02 +0000 Subject: [PATCH 055/100] [master] Update dependencies from dotnet/efcore (#23469) * Update dependencies from https://github.com/dotnet/efcore build 20200629.1 Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20328.1 -> To Version 5.0.0-preview.8.20329.1 * Update dependencies from https://github.com/dotnet/efcore build 20200629.2 Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20328.1 -> To Version 5.0.0-preview.8.20329.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b918917d86..f4c6245627 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - af10d4822fd79f09a32ce2a95eb6c75ce7f142a8 + 709535d8e7e4d0c91cfd5b8ff141f3a486381ed1 - + https://github.com/dotnet/efcore - af10d4822fd79f09a32ce2a95eb6c75ce7f142a8 + 709535d8e7e4d0c91cfd5b8ff141f3a486381ed1 - + https://github.com/dotnet/efcore - af10d4822fd79f09a32ce2a95eb6c75ce7f142a8 + 709535d8e7e4d0c91cfd5b8ff141f3a486381ed1 - + https://github.com/dotnet/efcore - af10d4822fd79f09a32ce2a95eb6c75ce7f142a8 + 709535d8e7e4d0c91cfd5b8ff141f3a486381ed1 - + https://github.com/dotnet/efcore - af10d4822fd79f09a32ce2a95eb6c75ce7f142a8 + 709535d8e7e4d0c91cfd5b8ff141f3a486381ed1 - + https://github.com/dotnet/efcore - af10d4822fd79f09a32ce2a95eb6c75ce7f142a8 + 709535d8e7e4d0c91cfd5b8ff141f3a486381ed1 - + https://github.com/dotnet/efcore - af10d4822fd79f09a32ce2a95eb6c75ce7f142a8 + 709535d8e7e4d0c91cfd5b8ff141f3a486381ed1 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index b00ca00d91..b2b9245531 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 - 5.0.0-preview.8.20328.1 + 5.0.0-preview.8.20329.2 + 5.0.0-preview.8.20329.2 + 5.0.0-preview.8.20329.2 + 5.0.0-preview.8.20329.2 + 5.0.0-preview.8.20329.2 + 5.0.0-preview.8.20329.2 + 5.0.0-preview.8.20329.2 3.2.0 - 5.0.0-preview.8.20329.2 - 5.0.0-preview.8.20329.2 - 5.0.0-preview.8.20329.2 - 5.0.0-preview.8.20329.2 - 5.0.0-preview.8.20329.2 - 5.0.0-preview.8.20329.2 - 5.0.0-preview.8.20329.2 + 5.0.0-preview.8.20329.4 + 5.0.0-preview.8.20329.4 + 5.0.0-preview.8.20329.4 + 5.0.0-preview.8.20329.4 + 5.0.0-preview.8.20329.4 + 5.0.0-preview.8.20329.4 + 5.0.0-preview.8.20329.4 false true + + linux-x64 diff --git a/src/Components/benchmarkapps/Wasm.Performance/README.md b/src/Components/benchmarkapps/Wasm.Performance/README.md index 6110956bfc..06fba416c8 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/README.md +++ b/src/Components/benchmarkapps/Wasm.Performance/README.md @@ -9,7 +9,7 @@ The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. T Here are the commands you would need to run it locally inside docker: -1. `dotnet publish -c Release -r linux-x64 Driver/Wasm.Performance.Driver.csproj` +1. `dotnet publish -c Release Driver/Wasm.Performance.Driver.csproj` 2. `docker build -t blazor-local -f ./local.dockerfile . ` 3. `docker run -it blazor-local` diff --git a/src/Components/benchmarkapps/Wasm.Performance/dockerfile b/src/Components/benchmarkapps/Wasm.Performance/dockerfile index 8237cb9e59..baf4d03861 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/dockerfile +++ b/src/Components/benchmarkapps/Wasm.Performance/dockerfile @@ -20,10 +20,11 @@ ADD https://api.github.com/repos/dotnet/aspnetcore/git/ref/heads/${gitBranch} /a RUN git init \ && git fetch https://github.com/aspnet/aspnetcore ${gitBranch} \ && git reset --hard FETCH_HEAD \ - && git submodule update --init + && git submodule update --init \ + && git remote add origin https://github.com/aspnet/aspnetcore RUN ./restore.sh -RUN .dotnet/dotnet publish -c Release -r linux-x64 -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj +RUN .dotnet/dotnet publish -c Release --no-restore -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj RUN chmod +x /app/Wasm.Performance.Driver WORKDIR /app diff --git a/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile b/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile index bccdc856f8..5971ed7ee0 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile +++ b/src/Components/benchmarkapps/Wasm.Performance/local.dockerfile @@ -3,7 +3,7 @@ FROM selenium/standalone-chrome:3.141.59-mercury as final ENV StressRunDuration=0 WORKDIR /app -COPY ./Driver/bin/Release/netcoreapp3.1/linux-x64/publish ./ +COPY ./Driver/bin/Release/net5.0/linux-x64/publish ./ COPY ./exec.sh ./ ENTRYPOINT [ "bash", "./exec.sh" ] diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/Microsoft.AspNetCore.Razor.Tools.csproj b/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/Microsoft.AspNetCore.Razor.Tools.csproj index 30885c51f1..1489542b02 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/Microsoft.AspNetCore.Razor.Tools.csproj +++ b/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/Microsoft.AspNetCore.Razor.Tools.csproj @@ -20,6 +20,7 @@ false + false diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/Microsoft.NET.Sdk.Razor.csproj b/src/Razor/Microsoft.NET.Sdk.Razor/src/Microsoft.NET.Sdk.Razor.csproj index 42cb964335..552d192460 100644 --- a/src/Razor/Microsoft.NET.Sdk.Razor/src/Microsoft.NET.Sdk.Razor.csproj +++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/Microsoft.NET.Sdk.Razor.csproj @@ -30,7 +30,7 @@ ReferenceOutputAssembly="false" IsImplicityDefined="false" SkipGetTargetFrameworkProperties="true" - UndefineProperties="TargetFramework;TargetFrameworks" /> + UndefineProperties="TargetFramework;TargetFrameworks;RuntimeIdentifier;PublishDir" /> From 408b1ac44359b37b70fa3e2bbe9575fca7726ccd Mon Sep 17 00:00:00 2001 From: kapsiR Date: Tue, 30 Jun 2020 18:21:33 +0200 Subject: [PATCH 063/100] Add autocomplete attributes to Identity UI (#14953) * Add autocomplete attributes to Identity UI V3 * Add autocomplete attributes to Identity UI V4 --- .../Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml | 2 +- .../Areas/Identity/Pages/V3/Account/ForgotPassword.cshtml | 2 +- .../UI/src/Areas/Identity/Pages/V3/Account/Login.cshtml | 4 ++-- .../Identity/Pages/V3/Account/Manage/ChangePassword.cshtml | 6 +++--- .../Pages/V3/Account/Manage/DeletePersonalData.cshtml | 4 ++-- .../src/Areas/Identity/Pages/V3/Account/Manage/Email.cshtml | 4 ++-- .../Identity/Pages/V3/Account/Manage/SetPassword.cshtml | 4 ++-- .../UI/src/Areas/Identity/Pages/V3/Account/Register.cshtml | 6 +++--- .../Areas/Identity/Pages/V3/Account/ResetPassword.cshtml | 6 +++--- .../Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml | 2 +- .../Areas/Identity/Pages/V4/Account/ForgotPassword.cshtml | 2 +- .../UI/src/Areas/Identity/Pages/V4/Account/Login.cshtml | 4 ++-- .../Identity/Pages/V4/Account/Manage/ChangePassword.cshtml | 6 +++--- .../Pages/V4/Account/Manage/DeletePersonalData.cshtml | 2 +- .../src/Areas/Identity/Pages/V4/Account/Manage/Email.cshtml | 4 ++-- .../Identity/Pages/V4/Account/Manage/SetPassword.cshtml | 4 ++-- .../UI/src/Areas/Identity/Pages/V4/Account/Register.cshtml | 6 +++--- .../Areas/Identity/Pages/V4/Account/ResetPassword.cshtml | 6 +++--- 18 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml index f73e2fe556..c2ae93e543 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml @@ -20,7 +20,7 @@
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ForgotPassword.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ForgotPassword.cshtml index 7541125984..f82b7475bc 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ForgotPassword.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ForgotPassword.cshtml @@ -13,7 +13,7 @@
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Login.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Login.cshtml index 8f4559fb78..444fbd4d0d 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Login.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Login.cshtml @@ -15,12 +15,12 @@
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ChangePassword.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ChangePassword.cshtml index 0cdc9c97a7..b089f16254 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ChangePassword.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ChangePassword.cshtml @@ -13,17 +13,17 @@
- +
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DeletePersonalData.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DeletePersonalData.cshtml index 4939c7fd5a..89f9318864 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DeletePersonalData.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DeletePersonalData.cshtml @@ -1,4 +1,4 @@ -@page +@page @model DeletePersonalDataModel @{ ViewData["Title"] = "Delete Personal Data"; @@ -21,7 +21,7 @@ {
- +
} diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/Email.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/Email.cshtml index 735c287802..53ebd0181b 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/Email.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/Email.cshtml @@ -20,7 +20,7 @@
} - else + else { @@ -28,7 +28,7 @@
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/SetPassword.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/SetPassword.cshtml index e82ce19df5..07bc021d27 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/SetPassword.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/SetPassword.cshtml @@ -17,12 +17,12 @@
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Register.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Register.cshtml index 78415afe1a..d9bc38dfcd 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Register.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Register.cshtml @@ -14,17 +14,17 @@
- +
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ResetPassword.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ResetPassword.cshtml index 97629b27cd..bab0c003fd 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ResetPassword.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ResetPassword.cshtml @@ -14,17 +14,17 @@
- +
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml index 7579138faa..40d365fd66 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml @@ -20,7 +20,7 @@
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ForgotPassword.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ForgotPassword.cshtml index 4570844df8..1ff47265d1 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ForgotPassword.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ForgotPassword.cshtml @@ -13,7 +13,7 @@
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Login.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Login.cshtml index 47b8750956..60d3605d83 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Login.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Login.cshtml @@ -15,12 +15,12 @@
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ChangePassword.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ChangePassword.cshtml index 4d5dda19ec..40921cc781 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ChangePassword.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ChangePassword.cshtml @@ -13,17 +13,17 @@
- +
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DeletePersonalData.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DeletePersonalData.cshtml index abcd16a82f..21eeb186a9 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DeletePersonalData.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DeletePersonalData.cshtml @@ -20,7 +20,7 @@ {
- +
} diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/Email.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/Email.cshtml index 996b8027c4..7e9687760c 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/Email.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/Email.cshtml @@ -22,7 +22,7 @@
} - else + else { @@ -30,7 +30,7 @@
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/SetPassword.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/SetPassword.cshtml index 593526746e..ebb490ef40 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/SetPassword.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/SetPassword.cshtml @@ -17,12 +17,12 @@
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Register.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Register.cshtml index 0a2f84f935..6b0d44ec8d 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Register.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Register.cshtml @@ -14,17 +14,17 @@
- +
- +
- +
diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ResetPassword.cshtml b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ResetPassword.cshtml index 953261844b..df51a6a258 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ResetPassword.cshtml +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ResetPassword.cshtml @@ -14,17 +14,17 @@
- +
- +
- +
From 9abbf4e1134cf1e699879756d1370c1d7c52e701 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Wed, 1 Jul 2020 02:11:51 +0600 Subject: [PATCH 064/100] Add documentation how to build installers (#21683) * Add documentation how to build installers Also add small index for the Docs folder * Fix PR comments * Update casing for the command line parameter * Remove duplicate section --- docs/BuildFromSource.md | 10 ++++++++++ docs/README.md | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/docs/BuildFromSource.md b/docs/BuildFromSource.md index 27648af722..693dabec86 100644 --- a/docs/BuildFromSource.md +++ b/docs/BuildFromSource.md @@ -230,6 +230,16 @@ TargetOsName | The base runtime identifier to build for (win, linux, After building ASP.NET Core from source, you will need to install and use your local version of ASP.NET Core. See ["Artifacts"](./Artifacts.md) for more explanation of the different folders produced by a build. +Building installers does not run as part of `build.cmd` run without parameters, so you should opt-in for building them: + +```ps1 +.\build.cmd -all -pack -arch x64 +.\build.cmd -all -pack -arch x86 -noBuildJava +.\build.cmd -buildInstallers +``` + +*Note*: Additional build steps listed above aren't necessary on Linux or macOS. + * Run the installers produced in `artifacts/installers/{Debug, Release}/` for your platform. * Add a NuGet.Config to your project directory with the following content: diff --git a/docs/README.md b/docs/README.md index f055ea32b5..230b8d7f51 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,3 +3,9 @@ Contributor documentation The primary audience for documentation in this folder is contributors to ASP.NET Core. If you are looking for documentation on how to *use* ASP.NET Core, go to . + +# ASP.NET Core developer workflow + +- [Building from source](BuildFromSource.md) +- [Troubleshooting build errors](BuildErrors.md) +- [Artifacts structure](Artifacts.md) From 71fef28e47db385efee14f80135391cf9ab516b6 Mon Sep 17 00:00:00 2001 From: Kahbazi Date: Wed, 1 Jul 2020 00:57:53 +0430 Subject: [PATCH 065/100] Remove user id from logs in order to comply GDPR (#17491) --- ...icrosoft.AspNetCore.Identity.netcoreapp.cs | 1 - src/Identity/Core/src/SignInManager.cs | 14 ++-- .../Extensions.Core/src/UserManager.cs | 46 ++++++------- .../src/IdentitySpecificationTestBase.cs | 4 +- .../src/UserManagerSpecificationTests.cs | 64 +++++++++---------- .../Pages/V3/Account/ExternalLogin.cshtml.cs | 2 +- .../Pages/V3/Account/LoginWith2fa.cshtml.cs | 6 +- .../Account/LoginWithRecoveryCode.cshtml.cs | 6 +- .../Manage/DeletePersonalData.cshtml.cs | 5 +- .../V3/Account/Manage/Disable2fa.cshtml.cs | 8 +-- .../Manage/DownloadPersonalData.cshtml.cs | 2 +- .../Manage/EnableAuthenticator.cshtml.cs | 2 +- .../Account/Manage/ExternalLogins.cshtml.cs | 2 +- .../Manage/GenerateRecoveryCodes.cshtml.cs | 8 +-- .../Manage/ResetAuthenticator.cshtml.cs | 4 +- .../Pages/V4/Account/ExternalLogin.cshtml.cs | 2 +- .../Pages/V4/Account/LoginWith2fa.cshtml.cs | 6 +- .../Account/LoginWithRecoveryCode.cshtml.cs | 6 +- .../Manage/DeletePersonalData.cshtml.cs | 4 +- .../V4/Account/Manage/Disable2fa.cshtml.cs | 8 +-- .../Manage/DownloadPersonalData.cshtml.cs | 2 +- .../Manage/EnableAuthenticator.cshtml.cs | 2 +- .../Account/Manage/ExternalLogins.cshtml.cs | 2 +- .../Manage/GenerateRecoveryCodes.cshtml.cs | 8 +-- .../Manage/ResetAuthenticator.cshtml.cs | 4 +- .../test/Identity.Test/SignInManagerTest.cs | 10 +-- 26 files changed, 111 insertions(+), 117 deletions(-) diff --git a/src/Identity/Core/ref/Microsoft.AspNetCore.Identity.netcoreapp.cs b/src/Identity/Core/ref/Microsoft.AspNetCore.Identity.netcoreapp.cs index 61b1891d26..1b1c625055 100644 --- a/src/Identity/Core/ref/Microsoft.AspNetCore.Identity.netcoreapp.cs +++ b/src/Identity/Core/ref/Microsoft.AspNetCore.Identity.netcoreapp.cs @@ -137,7 +137,6 @@ namespace Microsoft.AspNetCore.Identity public virtual bool IsSignedIn(System.Security.Claims.ClaimsPrincipal principal) { throw null; } [System.Diagnostics.DebuggerStepThroughAttribute] public virtual System.Threading.Tasks.Task IsTwoFactorClientRememberedAsync(TUser user) { throw null; } - [System.Diagnostics.DebuggerStepThroughAttribute] protected virtual System.Threading.Tasks.Task LockedOut(TUser user) { throw null; } [System.Diagnostics.DebuggerStepThroughAttribute] public virtual System.Threading.Tasks.Task PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure) { throw null; } diff --git a/src/Identity/Core/src/SignInManager.cs b/src/Identity/Core/src/SignInManager.cs index 5aa7aad531..0717a8af4b 100644 --- a/src/Identity/Core/src/SignInManager.cs +++ b/src/Identity/Core/src/SignInManager.cs @@ -144,17 +144,17 @@ namespace Microsoft.AspNetCore.Identity { if (Options.SignIn.RequireConfirmedEmail && !(await UserManager.IsEmailConfirmedAsync(user))) { - Logger.LogWarning(0, "User {userId} cannot sign in without a confirmed email.", await UserManager.GetUserIdAsync(user)); + Logger.LogWarning(0, "User cannot sign in without a confirmed email."); return false; } if (Options.SignIn.RequireConfirmedPhoneNumber && !(await UserManager.IsPhoneNumberConfirmedAsync(user))) { - Logger.LogWarning(1, "User {userId} cannot sign in without a confirmed phone number.", await UserManager.GetUserIdAsync(user)); + Logger.LogWarning(1, "User cannot sign in without a confirmed phone number."); return false; } if (Options.SignIn.RequireConfirmedAccount && !(await _confirmation.IsConfirmedAsync(UserManager, user))) { - Logger.LogWarning(4, "User {userId} cannot sign in without a confirmed account.", await UserManager.GetUserIdAsync(user)); + Logger.LogWarning(4, "User cannot sign in without a confirmed account."); return false; } return true; @@ -386,7 +386,7 @@ namespace Microsoft.AspNetCore.Identity return SignInResult.Success; } - Logger.LogWarning(2, "User {userId} failed to provide the correct password.", await UserManager.GetUserIdAsync(user)); + Logger.LogWarning(2, "User failed to provide the correct password."); if (UserManager.SupportsUserLockout && lockoutOnFailure) { @@ -840,10 +840,10 @@ namespace Microsoft.AspNetCore.Identity /// /// The user. /// A locked out SignInResult - protected virtual async Task LockedOut(TUser user) + protected virtual Task LockedOut(TUser user) { - Logger.LogWarning(3, "User {userId} is currently locked out.", await UserManager.GetUserIdAsync(user)); - return SignInResult.LockedOut; + Logger.LogWarning(3, "User is currently locked out."); + return Task.FromResult(SignInResult.LockedOut); } /// diff --git a/src/Identity/Extensions.Core/src/UserManager.cs b/src/Identity/Extensions.Core/src/UserManager.cs index fab5fd0d88..afecd4d235 100644 --- a/src/Identity/Extensions.Core/src/UserManager.cs +++ b/src/Identity/Extensions.Core/src/UserManager.cs @@ -610,7 +610,7 @@ namespace Microsoft.AspNetCore.Identity /// The name to normalize. /// A normalized value representing the specified . public virtual string NormalizeName(string name) - => (KeyNormalizer == null) ? name : KeyNormalizer.NormalizeName(name); + => (KeyNormalizer == null) ? name : KeyNormalizer.NormalizeName(name); /// /// Normalize email for consistent comparisons. @@ -618,7 +618,7 @@ namespace Microsoft.AspNetCore.Identity /// The email to normalize. /// A normalized value representing the specified . public virtual string NormalizeEmail(string email) - => (KeyNormalizer == null) ? email : KeyNormalizer.NormalizeEmail(email); + => (KeyNormalizer == null) ? email : KeyNormalizer.NormalizeEmail(email); private string ProtectPersonalData(string data) { @@ -716,7 +716,7 @@ namespace Microsoft.AspNetCore.Identity var success = result != PasswordVerificationResult.Failed; if (!success) { - Logger.LogWarning(0, "Invalid password for user {userId}.", await GetUserIdAsync(user)); + Logger.LogWarning(0, "Invalid password for user."); } return success; } @@ -763,7 +763,7 @@ namespace Microsoft.AspNetCore.Identity var hash = await passwordStore.GetPasswordHashAsync(user, CancellationToken); if (hash != null) { - Logger.LogWarning(1, "User {userId} already has a password.", await GetUserIdAsync(user)); + Logger.LogWarning(1, "User already has a password."); return IdentityResult.Failed(ErrorDescriber.UserAlreadyHasPassword()); } var result = await UpdatePasswordHash(passwordStore, user, password); @@ -804,7 +804,7 @@ namespace Microsoft.AspNetCore.Identity } return await UpdateUserAsync(user); } - Logger.LogWarning(2, "Change password failed for user {userId}.", await GetUserIdAsync(user)); + Logger.LogWarning(2, "Change password failed for user."); return IdentityResult.Failed(ErrorDescriber.PasswordMismatch()); } @@ -865,7 +865,7 @@ namespace Microsoft.AspNetCore.Identity var stamp = await securityStore.GetSecurityStampAsync(user, CancellationToken); if (stamp == null) { - Logger.LogWarning(15, "GetSecurityStampAsync for user {userId} failed because stamp was null.", await GetUserIdAsync(user)); + Logger.LogWarning(15, "GetSecurityStampAsync for user failed because stamp was null."); throw new InvalidOperationException(Resources.NullSecurityStamp); } return stamp; @@ -1021,7 +1021,7 @@ namespace Microsoft.AspNetCore.Identity var existingUser = await FindByLoginAsync(login.LoginProvider, login.ProviderKey); if (existingUser != null) { - Logger.LogWarning(4, "AddLogin for user {userId} failed because it was already associated with another user.", await GetUserIdAsync(user)); + Logger.LogWarning(4, "AddLogin for user failed because it was already associated with another user."); return IdentityResult.Failed(ErrorDescriber.LoginAlreadyAssociated()); } await loginStore.AddLoginAsync(user, login, CancellationToken); @@ -1216,7 +1216,7 @@ namespace Microsoft.AspNetCore.Identity var normalizedRole = NormalizeName(role); if (await userRoleStore.IsInRoleAsync(user, normalizedRole, CancellationToken)) { - return await UserAlreadyInRoleError(user, role); + return UserAlreadyInRoleError(role); } await userRoleStore.AddToRoleAsync(user, normalizedRole, CancellationToken); return await UpdateUserAsync(user); @@ -1249,7 +1249,7 @@ namespace Microsoft.AspNetCore.Identity var normalizedRole = NormalizeName(role); if (await userRoleStore.IsInRoleAsync(user, normalizedRole, CancellationToken)) { - return await UserAlreadyInRoleError(user, role); + return UserAlreadyInRoleError(role); } await userRoleStore.AddToRoleAsync(user, normalizedRole, CancellationToken); } @@ -1277,21 +1277,21 @@ namespace Microsoft.AspNetCore.Identity var normalizedRole = NormalizeName(role); if (!await userRoleStore.IsInRoleAsync(user, normalizedRole, CancellationToken)) { - return await UserNotInRoleError(user, role); + return UserNotInRoleError(role); } await userRoleStore.RemoveFromRoleAsync(user, normalizedRole, CancellationToken); return await UpdateUserAsync(user); } - private async Task UserAlreadyInRoleError(TUser user, string role) + private IdentityResult UserAlreadyInRoleError(string role) { - Logger.LogWarning(5, "User {userId} is already in role {role}.", await GetUserIdAsync(user), role); + Logger.LogWarning(5, "User is already in role {role}.", role); return IdentityResult.Failed(ErrorDescriber.UserAlreadyInRole(role)); } - private async Task UserNotInRoleError(TUser user, string role) + private IdentityResult UserNotInRoleError(string role) { - Logger.LogWarning(6, "User {userId} is not in role {role}.", await GetUserIdAsync(user), role); + Logger.LogWarning(6, "User is not in role {role}.", role); return IdentityResult.Failed(ErrorDescriber.UserNotInRole(role)); } @@ -1322,7 +1322,7 @@ namespace Microsoft.AspNetCore.Identity var normalizedRole = NormalizeName(role); if (!await userRoleStore.IsInRoleAsync(user, normalizedRole, CancellationToken)) { - return await UserNotInRoleError(user, role); + return UserNotInRoleError(role); } await userRoleStore.RemoveFromRoleAsync(user, normalizedRole, CancellationToken); } @@ -1627,7 +1627,7 @@ namespace Microsoft.AspNetCore.Identity if (!await VerifyChangePhoneNumberTokenAsync(user, token, phoneNumber)) { - Logger.LogWarning(7, "Change phone number for user {userId} failed with invalid token.", await GetUserIdAsync(user)); + Logger.LogWarning(7, "Change phone number for user failed with invalid token."); return IdentityResult.Failed(ErrorDescriber.InvalidToken()); } await store.SetPhoneNumberAsync(user, phoneNumber, CancellationToken); @@ -1689,7 +1689,7 @@ namespace Microsoft.AspNetCore.Identity } // Make sure the token is valid and the stamp matches - return VerifyUserTokenAsync(user, Options.Tokens.ChangePhoneNumberTokenProvider, ChangePhoneNumberTokenPurpose+":"+ phoneNumber, token); + return VerifyUserTokenAsync(user, Options.Tokens.ChangePhoneNumberTokenProvider, ChangePhoneNumberTokenPurpose + ":" + phoneNumber, token); } /// @@ -1725,7 +1725,7 @@ namespace Microsoft.AspNetCore.Identity if (!result) { - Logger.LogWarning(9, "VerifyUserTokenAsync() failed with purpose: {purpose} for user {userId}.", purpose, await GetUserIdAsync(user)); + Logger.LogWarning(9, "VerifyUserTokenAsync() failed with purpose: {purpose} for user.", purpose); } return result; } @@ -1827,7 +1827,7 @@ namespace Microsoft.AspNetCore.Identity var result = await _tokenProviders[tokenProvider].ValidateAsync("TwoFactor", token, this, user); if (!result) { - Logger.LogWarning(10, $"{nameof(VerifyTwoFactorTokenAsync)}() failed for user {await GetUserIdAsync(user)}."); + Logger.LogWarning(10, $"{nameof(VerifyTwoFactorTokenAsync)}() failed for user."); } return result; } @@ -2000,7 +2000,7 @@ namespace Microsoft.AspNetCore.Identity if (!await store.GetLockoutEnabledAsync(user, CancellationToken)) { - Logger.LogWarning(11, "Lockout for user {userId} failed because lockout is not enabled for this user.", await GetUserIdAsync(user)); + Logger.LogWarning(11, "Lockout for user failed because lockout is not enabled for this user."); return IdentityResult.Failed(ErrorDescriber.UserLockoutNotEnabled()); } await store.SetLockoutEndDateAsync(user, lockoutEnd, CancellationToken); @@ -2029,7 +2029,7 @@ namespace Microsoft.AspNetCore.Identity { return await UpdateUserAsync(user); } - Logger.LogWarning(12, "User {userId} is locked out.", await GetUserIdAsync(user)); + Logger.LogWarning(12, "User is locked out."); await store.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.Add(Options.Lockout.DefaultLockoutTimeSpan), CancellationToken); await store.ResetAccessFailedCountAsync(user, CancellationToken); @@ -2503,7 +2503,7 @@ namespace Microsoft.AspNetCore.Identity } if (errors.Count > 0) { - Logger.LogWarning(13, "User {userId} validation failed: {errors}.", await GetUserIdAsync(user), string.Join(";", errors.Select(e => e.Code))); + Logger.LogWarning(13, "User validation failed: {errors}.", string.Join(";", errors.Select(e => e.Code))); return IdentityResult.Failed(errors.ToArray()); } return IdentityResult.Success; @@ -2535,7 +2535,7 @@ namespace Microsoft.AspNetCore.Identity } if (!isValid) { - Logger.LogWarning(14, "User {userId} password validation failed: {errors}.", await GetUserIdAsync(user), string.Join(";", errors.Select(e => e.Code))); + Logger.LogWarning(14, "User password validation failed: {errors}.", string.Join(";", errors.Select(e => e.Code))); return IdentityResult.Failed(errors.ToArray()); } return IdentityResult.Success; diff --git a/src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs b/src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs index 4e67e26253..a9988a47e3 100644 --- a/src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs +++ b/src/Identity/Specification.Tests/src/IdentitySpecificationTestBase.cs @@ -486,7 +486,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await roleMgr.CreateAsync(role)); var result = await userMgr.RemoveFromRoleAsync(user, roleName); IdentityResultAssert.IsFailure(result, _errorDescriber.UserNotInRole(roleName)); - IdentityResultAssert.VerifyLogMessage(userMgr.Logger, $"User {await userMgr.GetUserIdAsync(user)} is not in role {roleName}."); + IdentityResultAssert.VerifyLogMessage(userMgr.Logger, $"User is not in role {roleName}."); } /// @@ -507,7 +507,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await userMgr.AddToRoleAsync(user, roleName)); Assert.True(await userMgr.IsInRoleAsync(user, roleName)); IdentityResultAssert.IsFailure(await userMgr.AddToRoleAsync(user, roleName), _errorDescriber.UserAlreadyInRole(roleName)); - IdentityResultAssert.VerifyLogMessage(userMgr.Logger, $"User {await userMgr.GetUserIdAsync(user)} is already in role {roleName}."); + IdentityResultAssert.VerifyLogMessage(userMgr.Logger, $"User is already in role {roleName}."); } /// diff --git a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs index f675482bfb..73d48be2f8 100644 --- a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs +++ b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs @@ -252,11 +252,11 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await manager.CreateAsync(newUser)); var error = _errorDescriber.InvalidUserName(""); IdentityResultAssert.IsFailure(await manager.SetUserNameAsync(newUser, ""), error); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(newUser)} validation failed: {error.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User validation failed: {error.Code}."); error = _errorDescriber.DuplicateUserName(newUsername); IdentityResultAssert.IsFailure(await manager.SetUserNameAsync(newUser, newUsername), error); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(newUser)} validation failed: {error.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User validation failed: {error.Code}."); } /// @@ -332,7 +332,7 @@ namespace Microsoft.AspNetCore.Identity.Test SetUserPasswordHash(user, manager.PasswordHasher.HashPassword(user, "New")); IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user)); Assert.False(await manager.CheckPasswordAsync(user, "password")); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"Invalid password for user {await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"Invalid password for user."); Assert.True(await manager.CheckPasswordAsync(user, "New")); } @@ -361,7 +361,7 @@ namespace Microsoft.AspNetCore.Identity.Test manager.UserValidators.Clear(); manager.UserValidators.Add(new AlwaysBadValidator()); IdentityResultAssert.IsFailure(await manager.CreateAsync(user), AlwaysBadValidator.ErrorMessage); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(user) ?? NullValue} validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); } /// @@ -377,7 +377,7 @@ namespace Microsoft.AspNetCore.Identity.Test manager.UserValidators.Clear(); manager.UserValidators.Add(new AlwaysBadValidator()); IdentityResultAssert.IsFailure(await manager.UpdateAsync(user), AlwaysBadValidator.ErrorMessage); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(user) ?? NullValue} validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); } /// @@ -394,7 +394,7 @@ namespace Microsoft.AspNetCore.Identity.Test manager.UserValidators.Add(new AlwaysBadValidator()); var result = await manager.CreateAsync(user); IdentityResultAssert.IsFailure(result, AlwaysBadValidator.ErrorMessage); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(user) ?? NullValue} validation failed: {AlwaysBadValidator.ErrorMessage.Code};{AlwaysBadValidator.ErrorMessage.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User validation failed: {AlwaysBadValidator.ErrorMessage.Code};{AlwaysBadValidator.ErrorMessage.Code}."); Assert.Equal(2, result.Errors.Count()); } @@ -442,7 +442,7 @@ namespace Microsoft.AspNetCore.Identity.Test manager.PasswordValidators.Add(new AlwaysBadValidator()); IdentityResultAssert.IsFailure(await manager.AddPasswordAsync(user, "password"), AlwaysBadValidator.ErrorMessage); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(user)} password validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User password validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); } /// @@ -530,7 +530,7 @@ namespace Microsoft.AspNetCore.Identity.Test manager.PasswordValidators.Add(new AlwaysBadValidator()); IdentityResultAssert.IsFailure(await manager.ChangePasswordAsync(user, "password", "new"), AlwaysBadValidator.ErrorMessage); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(user) ?? NullValue} password validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User password validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); } /// @@ -545,7 +545,7 @@ namespace Microsoft.AspNetCore.Identity.Test manager.PasswordValidators.Clear(); manager.PasswordValidators.Add(new AlwaysBadValidator()); IdentityResultAssert.IsFailure(await manager.CreateAsync(user, "password"), AlwaysBadValidator.ErrorMessage); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(user) ?? NullValue} password validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User password validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); } /// @@ -625,7 +625,7 @@ namespace Microsoft.AspNetCore.Identity.Test Assert.True(await manager.HasPasswordAsync(user)); IdentityResultAssert.IsFailure(await manager.AddPasswordAsync(user, "password"), "User already has a password set."); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(user)} already has a password."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User already has a password."); } /// @@ -829,7 +829,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password")); var result = await manager.ChangePasswordAsync(user, "bogus", "newpassword"); IdentityResultAssert.IsFailure(result, "Incorrect password."); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"Change password failed for user {await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"Change password failed for user."); } /// @@ -906,7 +906,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await manager.AddLoginAsync(user, login)); var result = await manager.AddLoginAsync(user, login); IdentityResultAssert.IsFailure(result, _errorDescriber.LoginAlreadyAssociated()); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"AddLogin for user {await manager.GetUserIdAsync(user)} failed because it was already associated with another user."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"AddLogin for user failed because it was already associated with another user."); } // Email tests @@ -1028,7 +1028,7 @@ namespace Microsoft.AspNetCore.Identity.Test manager.PasswordValidators.Add(new AlwaysBadValidator()); IdentityResultAssert.IsFailure(await manager.ResetPasswordAsync(user, token, newPassword), AlwaysBadValidator.ErrorMessage); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User {await manager.GetUserIdAsync(user)} password validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User password validation failed: {AlwaysBadValidator.ErrorMessage.Code}."); Assert.True(await manager.CheckPasswordAsync(user, password)); Assert.Equal(stamp, await manager.GetSecurityStampAsync(user)); } @@ -1050,7 +1050,7 @@ namespace Microsoft.AspNetCore.Identity.Test var stamp = await manager.GetSecurityStampAsync(user); Assert.NotNull(stamp); IdentityResultAssert.IsFailure(await manager.ResetPasswordAsync(user, "bogus", newPassword), "Invalid token."); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ResetPassword for user { await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ResetPassword for user."); Assert.True(await manager.CheckPasswordAsync(user, password)); Assert.Equal(stamp, await manager.GetSecurityStampAsync(user)); } @@ -1074,13 +1074,13 @@ namespace Microsoft.AspNetCore.Identity.Test Assert.True(await manager.VerifyUserTokenAsync(user, "Static", "test", token)); Assert.False(await manager.VerifyUserTokenAsync(user, "Static", "test2", token)); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: test2 for user { await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: test2 for user."); Assert.False(await manager.VerifyUserTokenAsync(user, "Static", "test", token + "a")); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: test for user { await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: test for user."); Assert.False(await manager.VerifyUserTokenAsync(user2, "Static", "test", token)); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: test for user { await manager.GetUserIdAsync(user2)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: test for user."); } /// @@ -1120,7 +1120,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await manager.CreateAsync(user)); IdentityResultAssert.IsFailure(await manager.ConfirmEmailAsync(user, "bogus"), "Invalid token."); Assert.False(await manager.IsEmailConfirmedAsync(user)); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user { await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user."); } /// @@ -1138,7 +1138,7 @@ namespace Microsoft.AspNetCore.Identity.Test Assert.NotNull(token); IdentityResultAssert.IsSuccess(await manager.ChangePasswordAsync(user, "password", "newpassword")); IdentityResultAssert.IsFailure(await manager.ConfirmEmailAsync(user, token), "Invalid token."); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user { await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user."); Assert.False(await manager.IsEmailConfirmedAsync(user)); } @@ -1161,7 +1161,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await mgr.AccessFailedAsync(user)); Assert.True(await mgr.IsLockedOutAsync(user)); Assert.True(await mgr.GetLockoutEndDateAsync(user) > DateTimeOffset.UtcNow.AddMinutes(55)); - IdentityResultAssert.VerifyLogMessage(mgr.Logger, $"User {await mgr.GetUserIdAsync(user)} is locked out."); + IdentityResultAssert.VerifyLogMessage(mgr.Logger, $"User is locked out."); Assert.Equal(0, await mgr.GetAccessFailedCountAsync(user)); } @@ -1187,7 +1187,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await mgr.AccessFailedAsync(user)); Assert.True(await mgr.IsLockedOutAsync(user)); Assert.True(await mgr.GetLockoutEndDateAsync(user) > DateTimeOffset.UtcNow.AddMinutes(55)); - IdentityResultAssert.VerifyLogMessage(mgr.Logger, $"User {await mgr.GetUserIdAsync(user)} is locked out."); + IdentityResultAssert.VerifyLogMessage(mgr.Logger, $"User is locked out."); Assert.Equal(0, await mgr.GetAccessFailedCountAsync(user)); } @@ -1243,7 +1243,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await mgr.AccessFailedAsync(user)); Assert.True(await mgr.IsLockedOutAsync(user)); Assert.True(await mgr.GetLockoutEndDateAsync(user) > DateTimeOffset.UtcNow.AddMinutes(55)); - IdentityResultAssert.VerifyLogMessage(mgr.Logger, $"User {await mgr.GetUserIdAsync(user)} is locked out."); + IdentityResultAssert.VerifyLogMessage(mgr.Logger, $"User is locked out."); Assert.Equal(0, await mgr.GetAccessFailedCountAsync(user)); } @@ -1277,7 +1277,7 @@ namespace Microsoft.AspNetCore.Identity.Test Assert.False(await mgr.GetLockoutEnabledAsync(user)); IdentityResultAssert.IsFailure(await mgr.SetLockoutEndDateAsync(user, new DateTimeOffset()), "Lockout is not enabled for this user."); - IdentityResultAssert.VerifyLogMessage(mgr.Logger, $"Lockout for user {await mgr.GetUserIdAsync(user)} failed because lockout is not enabled for this user."); + IdentityResultAssert.VerifyLogMessage(mgr.Logger, $"Lockout for user failed because lockout is not enabled for this user."); Assert.False(await mgr.IsLockedOutAsync(user)); } @@ -1407,7 +1407,7 @@ namespace Microsoft.AspNetCore.Identity.Test var stamp = await manager.GetSecurityStampAsync(user); IdentityResultAssert.IsFailure(await manager.ChangePhoneNumberAsync(user, "111-111-1111", "bogus"), "Invalid token."); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangePhoneNumber:111-111-1111 for user {await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangePhoneNumber:111-111-1111 for user."); Assert.False(await manager.IsPhoneNumberConfirmedAsync(user)); Assert.Equal("123-456-7890", await manager.GetPhoneNumberAsync(user)); Assert.Equal(stamp, await manager.GetSecurityStampAsync(user)); @@ -1486,8 +1486,8 @@ namespace Microsoft.AspNetCore.Identity.Test Assert.True(await manager.VerifyChangePhoneNumberTokenAsync(user, token2, num2)); Assert.False(await manager.VerifyChangePhoneNumberTokenAsync(user, "bogus", num1)); Assert.False(await manager.VerifyChangePhoneNumberTokenAsync(user, "bogus", num2)); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangePhoneNumber:{num1} for user {await manager.GetUserIdAsync(user)}."); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangePhoneNumber:{num2} for user {await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangePhoneNumber:{num1} for user."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangePhoneNumber:{num2} for user."); } /// @@ -1601,7 +1601,7 @@ namespace Microsoft.AspNetCore.Identity.Test var stamp = await manager.GetSecurityStampAsync(user); IdentityResultAssert.IsFailure(await manager.ChangeEmailAsync(user, "whatevah@foo.boop", "bogus"), "Invalid token."); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangeEmail:whatevah@foo.boop for user { await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangeEmail:whatevah@foo.boop for user."); Assert.False(await manager.IsEmailConfirmedAsync(user)); Assert.Equal(await manager.GetEmailAsync(user), oldEmail); Assert.Equal(stamp, await manager.GetSecurityStampAsync(user)); @@ -1625,7 +1625,7 @@ namespace Microsoft.AspNetCore.Identity.Test var token1 = await manager.GenerateChangeEmailTokenAsync(user, "forgot@alrea.dy"); IdentityResultAssert.IsFailure(await manager.ChangeEmailAsync(user, "oops@foo.boop", token1), "Invalid token."); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangeEmail:oops@foo.boop for user { await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyUserTokenAsync() failed with purpose: ChangeEmail:oops@foo.boop for user."); Assert.False(await manager.IsEmailConfirmedAsync(user)); Assert.Equal(await manager.GetEmailAsync(user), oldEmail); Assert.Equal(stamp, await manager.GetSecurityStampAsync(user)); @@ -1658,7 +1658,7 @@ namespace Microsoft.AspNetCore.Identity.Test IdentityResultAssert.IsSuccess(await manager.UpdateSecurityStampAsync(user)); } Assert.False(await manager.VerifyTwoFactorTokenAsync(user, factorId, token)); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyTwoFactorTokenAsync() failed for user {await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyTwoFactorTokenAsync() failed for user."); } /// @@ -1855,7 +1855,7 @@ namespace Microsoft.AspNetCore.Identity.Test Assert.NotNull(token); IdentityResultAssert.IsSuccess(await manager.UpdateSecurityStampAsync(user)); Assert.False(await manager.VerifyTwoFactorTokenAsync(user, factorId, token)); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyTwoFactorTokenAsync() failed for user {await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyTwoFactorTokenAsync() failed for user."); } /// @@ -1871,7 +1871,7 @@ namespace Microsoft.AspNetCore.Identity.Test var token = await manager.GenerateTwoFactorTokenAsync(user, "Phone"); Assert.NotNull(token); Assert.False(await manager.VerifyTwoFactorTokenAsync(user, "Email", token)); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyTwoFactorTokenAsync() failed for user {await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyTwoFactorTokenAsync() failed for user."); } /// @@ -1885,7 +1885,7 @@ namespace Microsoft.AspNetCore.Identity.Test var user = CreateTestUser(phoneNumber: "4251234567"); IdentityResultAssert.IsSuccess(await manager.CreateAsync(user)); Assert.False(await manager.VerifyTwoFactorTokenAsync(user, "Phone", "bogus")); - IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyTwoFactorTokenAsync() failed for user {await manager.GetUserIdAsync(user)}."); + IdentityResultAssert.VerifyLogMessage(manager.Logger, $"VerifyTwoFactorTokenAsync() failed for user."); } /// diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml.cs index 896a7656a5..7a65c2edb2 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/ExternalLogin.cshtml.cs @@ -148,7 +148,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Internal var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true); if (result.Succeeded) { - _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider); + _logger.LogInformation("User logged in with {LoginProvider} provider.", info.LoginProvider); return LocalRedirect(returnUrl); } if (result.IsLockedOut) diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/LoginWith2fa.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/LoginWith2fa.cshtml.cs index 4b64207a87..428557335f 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/LoginWith2fa.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/LoginWith2fa.cshtml.cs @@ -131,17 +131,17 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Internal if (result.Succeeded) { - _logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", userId); + _logger.LogInformation("User logged in with 2fa."); return LocalRedirect(returnUrl); } else if (result.IsLockedOut) { - _logger.LogWarning("User with ID '{UserId}' account locked out.", userId); + _logger.LogWarning("User account locked out."); return RedirectToPage("./Lockout"); } else { - _logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", userId); + _logger.LogWarning("Invalid authenticator code entered."); ModelState.AddModelError(string.Empty, "Invalid authenticator code."); return Page(); } diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/LoginWithRecoveryCode.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/LoginWithRecoveryCode.cshtml.cs index db2b4ffacb..26ab6a4eae 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/LoginWithRecoveryCode.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/LoginWithRecoveryCode.cshtml.cs @@ -114,17 +114,17 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Internal if (result.Succeeded) { - _logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", userId); + _logger.LogInformation("User logged in with a recovery code."); return LocalRedirect(returnUrl ?? Url.Content("~/")); } if (result.IsLockedOut) { - _logger.LogWarning("User with ID '{UserId}' account locked out.", userId); + _logger.LogWarning("User account locked out."); return RedirectToPage("./Lockout"); } else { - _logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", userId); + _logger.LogWarning("Invalid recovery code entered."); ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); return Page(); } diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DeletePersonalData.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DeletePersonalData.cshtml.cs index b393082805..498bd9feba 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DeletePersonalData.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DeletePersonalData.cshtml.cs @@ -105,15 +105,14 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal } var result = await _userManager.DeleteAsync(user); - var userId = await _userManager.GetUserIdAsync(user); if (!result.Succeeded) { - throw new InvalidOperationException($"Unexpected error occurred deleting user with ID '{userId}'."); + throw new InvalidOperationException($"Unexpected error occurred deleting user."); } await _signInManager.SignOutAsync(); - _logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId); + _logger.LogInformation("User deleted themselves."); return Redirect("~/"); } diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/Disable2fa.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/Disable2fa.cshtml.cs index f12c23038f..08604a1f70 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/Disable2fa.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/Disable2fa.cshtml.cs @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal if (!await _userManager.GetTwoFactorEnabledAsync(user)) { - throw new InvalidOperationException($"Cannot disable 2FA for user with ID '{_userManager.GetUserId(User)}' as it's not currently enabled."); + throw new InvalidOperationException($"Cannot disable 2FA as it's not currently enabled."); } return Page(); @@ -76,12 +76,12 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false); if (!disable2faResult.Succeeded) { - throw new InvalidOperationException($"Unexpected error occurred disabling 2FA for user with ID '{_userManager.GetUserId(User)}'."); + throw new InvalidOperationException($"Unexpected error occurred disabling 2FA."); } - _logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", _userManager.GetUserId(User)); + _logger.LogInformation("User has disabled 2fa."); StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app"; return RedirectToPage("./TwoFactorAuthentication"); } } -} \ No newline at end of file +} diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DownloadPersonalData.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DownloadPersonalData.cshtml.cs index d0fdadaf93..3d10008438 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DownloadPersonalData.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/DownloadPersonalData.cshtml.cs @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - _logger.LogInformation("User with ID '{UserId}' asked for their personal data.", _userManager.GetUserId(User)); + _logger.LogInformation("User asked for their personal data."); // Only include personal data for download var personalData = new Dictionary(); diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/EnableAuthenticator.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/EnableAuthenticator.cshtml.cs index 75e5efdf26..5702207f1b 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/EnableAuthenticator.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/EnableAuthenticator.cshtml.cs @@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal await _userManager.SetTwoFactorEnabledAsync(user, true); var userId = await _userManager.GetUserIdAsync(user); - _logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId); + _logger.LogInformation("User has enabled 2FA with an authenticator app."); StatusMessage = "Your authenticator app has been verified."; diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ExternalLogins.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ExternalLogins.cshtml.cs index 1360a5431b..c4676a9fbc 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ExternalLogins.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ExternalLogins.cshtml.cs @@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal var info = await _signInManager.GetExternalLoginInfoAsync(userId); if (info == null) { - throw new InvalidOperationException($"Unexpected error occurred loading external login info for user with ID '{userId}'."); + throw new InvalidOperationException($"Unexpected error occurred loading external login info."); } var result = await _userManager.AddLoginAsync(user, info); diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/GenerateRecoveryCodes.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/GenerateRecoveryCodes.cshtml.cs index d33ff2e3a3..347acec21b 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/GenerateRecoveryCodes.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/GenerateRecoveryCodes.cshtml.cs @@ -68,8 +68,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); if (!isTwoFactorEnabled) { - var userId = await _userManager.GetUserIdAsync(user); - throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' because they do not have 2FA enabled."); + throw new InvalidOperationException($"Cannot generate recovery codes because they do not have 2FA enabled."); } return Page(); @@ -84,16 +83,15 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal } var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); - var userId = await _userManager.GetUserIdAsync(user); if (!isTwoFactorEnabled) { - throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' as they do not have 2FA enabled."); + throw new InvalidOperationException($"Cannot generate recovery codes as they do not have 2FA enabled."); } var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); RecoveryCodes = recoveryCodes.ToArray(); - _logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId); + _logger.LogInformation("User has generated new 2FA recovery codes."); StatusMessage = "You have generated new recovery codes."; return RedirectToPage("./ShowRecoveryCodes"); } diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ResetAuthenticator.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ResetAuthenticator.cshtml.cs index 213a016a02..f83fb9c77c 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ResetAuthenticator.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V3/Account/Manage/ResetAuthenticator.cshtml.cs @@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal await _userManager.SetTwoFactorEnabledAsync(user, false); await _userManager.ResetAuthenticatorKeyAsync(user); var userId = await _userManager.GetUserIdAsync(user); - _logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", userId); + _logger.LogInformation("User has reset their authentication app key."); await _signInManager.RefreshSignInAsync(user); StatusMessage = "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key."; @@ -83,4 +83,4 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Manage.Internal return RedirectToPage("./EnableAuthenticator"); } } -} \ No newline at end of file +} diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml.cs index 5b580b865c..18b9752170 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/ExternalLogin.cshtml.cs @@ -145,7 +145,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Internal var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true); if (result.Succeeded) { - _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider); + _logger.LogInformation("User logged in with {LoginProvider} provider.", info.LoginProvider); return LocalRedirect(returnUrl); } if (result.IsLockedOut) diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/LoginWith2fa.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/LoginWith2fa.cshtml.cs index ae71b4a0a8..c02fd82b5d 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/LoginWith2fa.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/LoginWith2fa.cshtml.cs @@ -130,17 +130,17 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Internal if (result.Succeeded) { - _logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", userId); + _logger.LogInformation("User logged in with 2fa."); return LocalRedirect(returnUrl); } else if (result.IsLockedOut) { - _logger.LogWarning("User with ID '{UserId}' account locked out.", userId); + _logger.LogWarning("User account locked out."); return RedirectToPage("./Lockout"); } else { - _logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", userId); + _logger.LogWarning("Invalid authenticator code entered."); ModelState.AddModelError(string.Empty, "Invalid authenticator code."); return Page(); } diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/LoginWithRecoveryCode.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/LoginWithRecoveryCode.cshtml.cs index b3b4af95c3..629c516df7 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/LoginWithRecoveryCode.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/LoginWithRecoveryCode.cshtml.cs @@ -113,17 +113,17 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Internal if (result.Succeeded) { - _logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", userId); + _logger.LogInformation("User logged in with a recovery code."); return LocalRedirect(returnUrl ?? Url.Content("~/")); } if (result.IsLockedOut) { - _logger.LogWarning("User with ID '{UserId}' account locked out.", userId); + _logger.LogWarning("User account locked out."); return RedirectToPage("./Lockout"); } else { - _logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", userId); + _logger.LogWarning("Invalid recovery code entered."); ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); return Page(); } diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DeletePersonalData.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DeletePersonalData.cshtml.cs index 3a918fccb4..34372d197e 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DeletePersonalData.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DeletePersonalData.cshtml.cs @@ -108,12 +108,12 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal var userId = await _userManager.GetUserIdAsync(user); if (!result.Succeeded) { - throw new InvalidOperationException($"Unexpected error occurred deleting user with ID '{userId}'."); + throw new InvalidOperationException($"Unexpected error occurred deleting user."); } await _signInManager.SignOutAsync(); - _logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId); + _logger.LogInformation("User deleted themselves."); return Redirect("~/"); } diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/Disable2fa.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/Disable2fa.cshtml.cs index 1cb5c66b5f..1a844ca1d6 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/Disable2fa.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/Disable2fa.cshtml.cs @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal if (!await _userManager.GetTwoFactorEnabledAsync(user)) { - throw new InvalidOperationException($"Cannot disable 2FA for user with ID '{_userManager.GetUserId(User)}' as it's not currently enabled."); + throw new InvalidOperationException($"Cannot disable 2FA for user as it's not currently enabled."); } return Page(); @@ -76,12 +76,12 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false); if (!disable2faResult.Succeeded) { - throw new InvalidOperationException($"Unexpected error occurred disabling 2FA for user with ID '{_userManager.GetUserId(User)}'."); + throw new InvalidOperationException($"Unexpected error occurred disabling 2FA."); } - _logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", _userManager.GetUserId(User)); + _logger.LogInformation("User has disabled 2fa."); StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app"; return RedirectToPage("./TwoFactorAuthentication"); } } -} \ No newline at end of file +} diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DownloadPersonalData.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DownloadPersonalData.cshtml.cs index 38d077f014..378556879e 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DownloadPersonalData.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/DownloadPersonalData.cshtml.cs @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - _logger.LogInformation("User with ID '{UserId}' asked for their personal data.", _userManager.GetUserId(User)); + _logger.LogInformation("User asked for their personal data."); // Only include personal data for download var personalData = new Dictionary(); diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/EnableAuthenticator.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/EnableAuthenticator.cshtml.cs index 069f6c3d7b..66cab7ef9b 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/EnableAuthenticator.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/EnableAuthenticator.cshtml.cs @@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal await _userManager.SetTwoFactorEnabledAsync(user, true); var userId = await _userManager.GetUserIdAsync(user); - _logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId); + _logger.LogInformation("User has enabled 2FA with an authenticator app."); StatusMessage = "Your authenticator app has been verified."; diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ExternalLogins.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ExternalLogins.cshtml.cs index 0a4754bf3a..2d00de4082 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ExternalLogins.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ExternalLogins.cshtml.cs @@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal var info = await _signInManager.GetExternalLoginInfoAsync(userId); if (info == null) { - throw new InvalidOperationException($"Unexpected error occurred loading external login info for user with ID '{userId}'."); + throw new InvalidOperationException($"Unexpected error occurred loading external login info."); } var result = await _userManager.AddLoginAsync(user, info); diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/GenerateRecoveryCodes.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/GenerateRecoveryCodes.cshtml.cs index afe71d3ed1..d8f54f7732 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/GenerateRecoveryCodes.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/GenerateRecoveryCodes.cshtml.cs @@ -68,8 +68,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); if (!isTwoFactorEnabled) { - var userId = await _userManager.GetUserIdAsync(user); - throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' because they do not have 2FA enabled."); + throw new InvalidOperationException($"Cannot generate recovery codes for user because they do not have 2FA enabled."); } return Page(); @@ -84,16 +83,15 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal } var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); - var userId = await _userManager.GetUserIdAsync(user); if (!isTwoFactorEnabled) { - throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' as they do not have 2FA enabled."); + throw new InvalidOperationException($"Cannot generate recovery codes for user as they do not have 2FA enabled."); } var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); RecoveryCodes = recoveryCodes.ToArray(); - _logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId); + _logger.LogInformation("User has generated new 2FA recovery codes."); StatusMessage = "You have generated new recovery codes."; return RedirectToPage("./ShowRecoveryCodes"); } diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ResetAuthenticator.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ResetAuthenticator.cshtml.cs index b8463b6976..c87b96e770 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ResetAuthenticator.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/ResetAuthenticator.cshtml.cs @@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal await _userManager.SetTwoFactorEnabledAsync(user, false); await _userManager.ResetAuthenticatorKeyAsync(user); var userId = await _userManager.GetUserIdAsync(user); - _logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", userId); + _logger.LogInformation("User has reset their authentication app key."); await _signInManager.RefreshSignInAsync(user); StatusMessage = "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key."; @@ -82,4 +82,4 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Manage.Internal return RedirectToPage("./EnableAuthenticator"); } } -} \ No newline at end of file +} diff --git a/src/Identity/test/Identity.Test/SignInManagerTest.cs b/src/Identity/test/Identity.Test/SignInManagerTest.cs index 2135608e81..05839a3580 100644 --- a/src/Identity/test/Identity.Test/SignInManagerTest.cs +++ b/src/Identity/test/Identity.Test/SignInManagerTest.cs @@ -132,7 +132,7 @@ namespace Microsoft.AspNetCore.Identity.Test // Assert Assert.False(result.Succeeded); Assert.True(result.IsLockedOut); - Assert.Contains($"User {user.Id} is currently locked out.", logger.LogMessages); + Assert.Contains($"User is currently locked out.", logger.LogMessages); manager.Verify(); } @@ -162,7 +162,7 @@ namespace Microsoft.AspNetCore.Identity.Test // Assert Assert.False(result.Succeeded); Assert.True(result.IsLockedOut); - Assert.Contains($"User {user.Id} is currently locked out.", logger.LogMessages); + Assert.Contains($"User is currently locked out.", logger.LogMessages); manager.Verify(); } @@ -771,7 +771,7 @@ namespace Microsoft.AspNetCore.Identity.Test // Assert Assert.False(result.Succeeded); Assert.False(checkResult.Succeeded); - Assert.Contains($"User {user.Id} failed to provide the correct password.", logger.LogMessages); + Assert.Contains($"User failed to provide the correct password.", logger.LogMessages); manager.Verify(); context.Verify(); } @@ -881,7 +881,7 @@ namespace Microsoft.AspNetCore.Identity.Test Assert.Equal(confirmed, result.Succeeded); Assert.NotEqual(confirmed, result.IsNotAllowed); - var message = $"User {user.Id} cannot sign in without a confirmed email."; + var message = $"User cannot sign in without a confirmed email."; if (!confirmed) { Assert.Contains(message, logger.LogMessages); @@ -935,7 +935,7 @@ namespace Microsoft.AspNetCore.Identity.Test Assert.Equal(confirmed, result.Succeeded); Assert.NotEqual(confirmed, result.IsNotAllowed); - var message = $"User {user.Id} cannot sign in without a confirmed phone number."; + var message = $"User cannot sign in without a confirmed phone number."; if (!confirmed) { Assert.Contains(message, logger.LogMessages); From 9ef1b35b7a480f6e9d26eb5251a18a7d87e65265 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2020 21:17:48 +0000 Subject: [PATCH 066/100] Update dependencies from https://github.com/dotnet/efcore build 20200630.1 (#23506) Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20329.4 -> To Version 5.0.0-preview.8.20330.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a93d5b94d3..4d514c723f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 63d890df58be5a7d733f80cde14f456112be7640 + 4795eee89fd67a05ae3aa288509c57200f0d7c89 - + https://github.com/dotnet/efcore - 63d890df58be5a7d733f80cde14f456112be7640 + 4795eee89fd67a05ae3aa288509c57200f0d7c89 - + https://github.com/dotnet/efcore - 63d890df58be5a7d733f80cde14f456112be7640 + 4795eee89fd67a05ae3aa288509c57200f0d7c89 - + https://github.com/dotnet/efcore - 63d890df58be5a7d733f80cde14f456112be7640 + 4795eee89fd67a05ae3aa288509c57200f0d7c89 - + https://github.com/dotnet/efcore - 63d890df58be5a7d733f80cde14f456112be7640 + 4795eee89fd67a05ae3aa288509c57200f0d7c89 - + https://github.com/dotnet/efcore - 63d890df58be5a7d733f80cde14f456112be7640 + 4795eee89fd67a05ae3aa288509c57200f0d7c89 - + https://github.com/dotnet/efcore - 63d890df58be5a7d733f80cde14f456112be7640 + 4795eee89fd67a05ae3aa288509c57200f0d7c89 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index aee2a70852..505edcc2ca 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.8.20329.4 - 5.0.0-preview.8.20329.4 - 5.0.0-preview.8.20329.4 - 5.0.0-preview.8.20329.4 - 5.0.0-preview.8.20329.4 - 5.0.0-preview.8.20329.4 - 5.0.0-preview.8.20329.4 + 5.0.0-preview.8.20330.1 + 5.0.0-preview.8.20330.1 + 5.0.0-preview.8.20330.1 + 5.0.0-preview.8.20330.1 + 5.0.0-preview.8.20330.1 + 5.0.0-preview.8.20330.1 + 5.0.0-preview.8.20330.1 false true diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs index ffa5da4de1..a63c8c4dfd 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs @@ -333,7 +333,7 @@ namespace Templates.Test public async Task BlazorWasmStandaloneTemplate_IndividualAuth_Works() { var project = await ProjectFactory.GetOrCreateProject("blazorstandaloneindividual", Output); - project.TargetFramework = "netstandard2.1"; + project.RuntimeIdentifier = "browser-wasm"; var createResult = await project.RunDotNetNewAsync("blazorwasm", args: new[] { "-au", diff --git a/src/ProjectTemplates/Shared/ProjectFactoryFixture.cs b/src/ProjectTemplates/Shared/ProjectFactoryFixture.cs index 41279ca0aa..d268ce8742 100644 --- a/src/ProjectTemplates/Shared/ProjectFactoryFixture.cs +++ b/src/ProjectTemplates/Shared/ProjectFactoryFixture.cs @@ -44,7 +44,7 @@ namespace Templates.Test.Helpers DiagnosticsMessageSink = DiagnosticsMessageSink, ProjectGuid = Path.GetRandomFileName().Replace(".", string.Empty) }; - project.ProjectName = $"AspNet.{key}.{project.ProjectGuid}"; + project.ProjectName = $"AspNet.{project.ProjectGuid}"; var assemblyPath = GetType().Assembly; var basePath = GetTemplateFolderBasePath(assemblyPath); diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Components.Wasm.targets b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Components.Wasm.targets index fff9969bcb..1d293e3ef4 100644 --- a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Components.Wasm.targets +++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Components.Wasm.targets @@ -92,6 +92,7 @@ Copyright (c) .NET Foundation. All rights reserved. + <_BlazorJSFile Include="$(BlazorWebAssemblyJSPath)" /> <_BlazorJSFile Include="$(BlazorWebAssemblyJSMapPath)" Condition="Exists('$(BlazorWebAssemblyJSMapPath)')" /> @@ -140,7 +141,7 @@ Copyright (c) .NET Foundation. All rights reserved. - + <_BlazorOutputWithTargetPath Include="@(_BlazorReadSatelliteAssembly)" @@ -162,6 +163,12 @@ Copyright (c) .NET Foundation. All rights reserved. + + + - + https://github.com/dotnet/runtime - 98b6284e020845c04bc7b1cefdcd01ffe7a4a8c0 + 2d0249e7ae75647c313623b7322cd71a72870deb - + https://github.com/dotnet/runtime - 98b6284e020845c04bc7b1cefdcd01ffe7a4a8c0 + 2d0249e7ae75647c313623b7322cd71a72870deb - + https://github.com/dotnet/runtime - 98b6284e020845c04bc7b1cefdcd01ffe7a4a8c0 + 2d0249e7ae75647c313623b7322cd71a72870deb https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index 505edcc2ca..07bdb0e8d1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,69 +66,69 @@ 3.7.0-4.20319.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 - 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20328.6 + 5.0.0-preview.8.20330.14 3.2.0 diff --git a/src/Http/Http.Abstractions/test/HttpResponseWritingExtensionsTests.cs b/src/Http/Http.Abstractions/test/HttpResponseWritingExtensionsTests.cs index 0591abdce6..ed0c103006 100644 --- a/src/Http/Http.Abstractions/test/HttpResponseWritingExtensionsTests.cs +++ b/src/Http/Http.Abstractions/test/HttpResponseWritingExtensionsTests.cs @@ -80,7 +80,9 @@ namespace Microsoft.AspNetCore.Http { Encoding.BigEndianUnicode }, { Encoding.Unicode }, { Encoding.UTF32 }, +#pragma warning disable CS0618, MSLIB0001 // Type or member is obsolete { Encoding.UTF7 }, +#pragma warning restore CS0618, MSLIB0001 // Type or member is obsolete { Encoding.UTF8 } }; diff --git a/src/Http/Http/src/Features/FormFeature.cs b/src/Http/Http/src/Features/FormFeature.cs index c5a288e0bb..d7f1888139 100644 --- a/src/Http/Http/src/Features/FormFeature.cs +++ b/src/Http/Http/src/Features/FormFeature.cs @@ -276,7 +276,9 @@ namespace Microsoft.AspNetCore.Http.Features private static Encoding FilterEncoding(Encoding? encoding) { // UTF-7 is insecure and should not be honored. UTF-8 will succeed for most cases. +#pragma warning disable CS0618, MSLIB0001 // Type or member is obsolete if (encoding == null || Encoding.UTF7.Equals(encoding)) +#pragma warning restore CS0618, MSLIB0001 // Type or member is obsolete { return Encoding.UTF8; } diff --git a/src/Http/WebUtilities/src/FormPipeReader.cs b/src/Http/WebUtilities/src/FormPipeReader.cs index 3ce6e03b29..bcb553458d 100644 --- a/src/Http/WebUtilities/src/FormPipeReader.cs +++ b/src/Http/WebUtilities/src/FormPipeReader.cs @@ -47,8 +47,10 @@ namespace Microsoft.AspNetCore.WebUtilities public FormPipeReader(PipeReader pipeReader, Encoding encoding) { +#pragma warning disable CS0618, MSLIB0001 // Type or member is obsolete if (encoding == Encoding.UTF7) { +#pragma warning restore CS0618, MSLIB0001 // Type or member is obsolete throw new ArgumentException("UTF7 is unsupported and insecure. Please select a different encoding."); } diff --git a/src/Http/WebUtilities/src/MultipartSectionStreamExtensions.cs b/src/Http/WebUtilities/src/MultipartSectionStreamExtensions.cs index f0a51656ad..58c16bd605 100644 --- a/src/Http/WebUtilities/src/MultipartSectionStreamExtensions.cs +++ b/src/Http/WebUtilities/src/MultipartSectionStreamExtensions.cs @@ -34,20 +34,22 @@ namespace Microsoft.AspNetCore.WebUtilities MediaTypeHeaderValue.TryParse(section.ContentType, out var sectionMediaType); var streamEncoding = sectionMediaType?.Encoding; +#pragma warning disable CS0618, MSLIB0001 // Type or member is obsolete if (streamEncoding == null || streamEncoding == Encoding.UTF7) +#pragma warning restore CS0618, MSLIB0001 // Type or member is obsolete { streamEncoding = Encoding.UTF8; } using (var reader = new StreamReader( - section.Body, + section.Body, streamEncoding, detectEncodingFromByteOrderMarks: true, - bufferSize: 1024, + bufferSize: 1024, leaveOpen: true)) { return await reader.ReadToEndAsync(); } - } + } } } diff --git a/src/Mvc/Mvc.Core/test/ContentResultTest.cs b/src/Mvc/Mvc.Core/test/ContentResultTest.cs index a9b044cb2c..afe9675a69 100644 --- a/src/Mvc/Mvc.Core/test/ContentResultTest.cs +++ b/src/Mvc/Mvc.Core/test/ContentResultTest.cs @@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Mvc Content = null, ContentType = new MediaTypeHeaderValue("text/plain") { - Encoding = Encoding.UTF7 + Encoding = Encoding.Unicode }.ToString() }; var httpContext = GetHttpContext(); @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Mvc await contentResult.ExecuteResultAsync(actionContext); // Assert - MediaTypeAssert.Equal("text/plain; charset=utf-7", httpContext.Response.ContentType); + MediaTypeAssert.Equal("text/plain; charset=utf-16", httpContext.Response.ContentType); } public static TheoryData ContentResultContentTypeData diff --git a/src/Mvc/test/Mvc.FunctionalTests/ApiBehaviorTest.cs b/src/Mvc/test/Mvc.FunctionalTests/ApiBehaviorTest.cs index ca92aba1b6..6762102451 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/ApiBehaviorTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/ApiBehaviorTest.cs @@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests // Arrange var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/contact") { - Content = new StringContent("some content", Encoding.UTF7, "application/json"), + Content = new StringContent("some content", Encoding.Latin1, "application/json"), }; // Act From 7f6147d50fd68f7a8b89ba72fc2293b1f085abd8 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 1 Jul 2020 13:46:56 -0700 Subject: [PATCH 075/100] Use containers instead of dockerbuild.sh (#23497) --- .azure/pipelines/ci.yml | 6 ++++-- .azure/pipelines/jobs/default-build.yml | 2 ++ eng/docker/alpine.Dockerfile | 28 ------------------------- eng/docker/ubuntu-alpine37.Dockerfile | 19 ----------------- 4 files changed, 6 insertions(+), 49 deletions(-) delete mode 100644 eng/docker/alpine.Dockerfile delete mode 100644 eng/docker/ubuntu-alpine37.Dockerfile diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index 51ce25fea8..86946e879b 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -433,7 +433,8 @@ stages: jobName: Linux_musl_x64_build jobDisplayName: "Build: Linux Musl x64" agentOs: Linux - buildScript: ./dockerbuild.sh alpine + container: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.9-WithNode-0fc54a3-20190918214015 + buildScript: ./build.sh buildArgs: --arch x64 --os-name linux-musl @@ -466,7 +467,8 @@ stages: jobDisplayName: "Build: Linux Musl ARM64" agentOs: Linux useHostedUbuntu: false - buildScript: ./dockerbuild.sh ubuntu-alpine37 + container: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-alpine-20200413125008-406629a + buildScript: ./build.sh buildArgs: --arch arm64 --os-name linux-musl diff --git a/.azure/pipelines/jobs/default-build.yml b/.azure/pipelines/jobs/default-build.yml index 3906f93cdf..57c61890a5 100644 --- a/.azure/pipelines/jobs/default-build.yml +++ b/.azure/pipelines/jobs/default-build.yml @@ -114,6 +114,8 @@ jobs: name: NetCoreInternal-Pool # Visual Studio Enterprise - contains some stuff, like SQL Server and IIS Express, that we use for testing queue: BuildPool.Server.Amd64.VS2019 + ${{ if ne(parameters.container, '') }}: + container: ${{ parameters.container }} variables: - AgentOsName: ${{ parameters.agentOs }} - ASPNETCORE_TEST_LOG_MAXPATH: "200" # Keep test log file name length low enough for artifact zipping diff --git a/eng/docker/alpine.Dockerfile b/eng/docker/alpine.Dockerfile deleted file mode 100644 index bc1547d1df..0000000000 --- a/eng/docker/alpine.Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM microsoft/dotnet:2.1.0-preview1-runtime-deps-alpine -ARG USER -ARG USER_ID -ARG GROUP_ID -ARG WORKDIR - -WORKDIR ${WORKDIR} -RUN mkdir -p "/home/$USER" && chown "${USER_ID}:${GROUP_ID}" "/home/$USER" -ENV HOME "/home/$USER" - -RUN apk add --no-cache \ - bash \ - wget \ - git \ - jq \ - curl \ - icu-libs \ - openssl - -USER $USER_ID:$GROUP_ID - -# Disable the invariant mode (set in base image) -ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false -ENV LC_ALL en_US.UTF-8 -ENV LANG en_US.UTF-8 - -# Skip package initilization -ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 diff --git a/eng/docker/ubuntu-alpine37.Dockerfile b/eng/docker/ubuntu-alpine37.Dockerfile deleted file mode 100644 index 859098f04e..0000000000 --- a/eng/docker/ubuntu-alpine37.Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-alpine10fcdcf-20190208200917 -ARG USER -ARG USER_ID -ARG GROUP_ID -ARG WORKDIR - -WORKDIR ${WORKDIR} -RUN mkdir -p "/home/$USER" && chown "${USER_ID}:${GROUP_ID}" "/home/$USER" -ENV HOME "/home/$USER" - -USER $USER_ID:$GROUP_ID - -# Disable the invariant mode (set in base image) -ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false -ENV LC_ALL en_US.UTF-8 -ENV LANG en_US.UTF-8 - -# Skip package initilization -ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 From 01de3552890b7f08270735ffc46a37fe4b129139 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Thu, 2 Jul 2020 09:48:05 +1200 Subject: [PATCH 076/100] Don't set StatusCode in WriteAsJsonAsync (#23583) --- .../src/HttpResponseJsonExtensions.cs | 2 -- .../test/HttpResponseJsonExtensionsTests.cs | 34 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs b/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs index a3bfbb6958..ae8e1ed6ca 100644 --- a/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs +++ b/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs @@ -77,7 +77,6 @@ namespace Microsoft.AspNetCore.Http.Json options ??= ResolveSerializerOptions(response.HttpContext); response.ContentType = contentType ?? JsonConstants.JsonContentTypeWithCharset; - response.StatusCode = StatusCodes.Status200OK; return JsonSerializer.SerializeAsync(response.Body, value!, options, cancellationToken); } @@ -150,7 +149,6 @@ namespace Microsoft.AspNetCore.Http.Json options ??= ResolveSerializerOptions(response.HttpContext); response.ContentType = contentType ?? JsonConstants.JsonContentTypeWithCharset; - response.StatusCode = StatusCodes.Status200OK; return JsonSerializer.SerializeAsync(response.Body, value, type, options, cancellationToken); } diff --git a/src/Http/Http.Extensions/test/HttpResponseJsonExtensionsTests.cs b/src/Http/Http.Extensions/test/HttpResponseJsonExtensionsTests.cs index 74add9b9e1..be01516515 100644 --- a/src/Http/Http.Extensions/test/HttpResponseJsonExtensionsTests.cs +++ b/src/Http/Http.Extensions/test/HttpResponseJsonExtensionsTests.cs @@ -88,6 +88,23 @@ namespace Microsoft.AspNetCore.Http.Extensions.Tests } } + [Fact] + public async Task WriteAsJsonAsyncGeneric_CustomStatusCode_StatusCodeUnchanged() + { + // Arrange + var body = new MemoryStream(); + var context = new DefaultHttpContext(); + context.Response.Body = body; + + // Act + context.Response.StatusCode = StatusCodes.Status418ImATeapot; + await context.Response.WriteAsJsonAsync(1); + + // Assert + Assert.Equal(JsonConstants.JsonContentTypeWithCharset, context.Response.ContentType); + Assert.Equal(StatusCodes.Status418ImATeapot, context.Response.StatusCode); + } + [Fact] public async Task WriteAsJsonAsyncGeneric_WithContentType_JsonResponseWithCustomContentType() { @@ -223,6 +240,23 @@ namespace Microsoft.AspNetCore.Http.Extensions.Tests Assert.Equal(@"{""stringProperty"":""激光這兩個字是甚麼意思""}", data); } + [Fact] + public async Task WriteAsJsonAsync_CustomStatusCode_StatusCodeUnchanged() + { + // Arrange + var body = new MemoryStream(); + var context = new DefaultHttpContext(); + context.Response.Body = body; + + // Act + context.Response.StatusCode = StatusCodes.Status418ImATeapot; + await context.Response.WriteAsJsonAsync(1, typeof(int)); + + // Assert + Assert.Equal(JsonConstants.JsonContentTypeWithCharset, context.Response.ContentType); + Assert.Equal(StatusCodes.Status418ImATeapot, context.Response.StatusCode); + } + public class TestObject { public string? StringProperty { get; set; } From 2cbc7a44cfb1ae03cad72164db3e59a285e2d755 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 1 Jul 2020 22:59:34 +0100 Subject: [PATCH 077/100] Use hasOwnProperty in a more robust way in JS interop. Fixes #23448 (#23573) * Use hasOwnProperty in a more robust way in JS interop. Fixes #23448 * Update JS --- src/Components/Web.JS/dist/Release/blazor.server.js | 2 +- src/Components/Web.JS/dist/Release/blazor.webassembly.js | 2 +- .../Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Components/Web.JS/dist/Release/blazor.server.js b/src/Components/Web.JS/dist/Release/blazor.server.js index 39d7648d11..00f5db4495 100644 --- a/src/Components/Web.JS/dist/Release/blazor.server.js +++ b/src/Components/Web.JS/dist/Release/blazor.server.js @@ -1,4 +1,4 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=53)}([function(e,t,n){"use strict";var r;n.d(t,"a",(function(){return r})),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(r||(r={}))},function(e,t,n){"use strict";(function(e){n.d(t,"e",(function(){return c})),n.d(t,"a",(function(){return u})),n.d(t,"c",(function(){return l})),n.d(t,"g",(function(){return f})),n.d(t,"i",(function(){return h})),n.d(t,"j",(function(){return p})),n.d(t,"f",(function(){return d})),n.d(t,"d",(function(){return g})),n.d(t,"b",(function(){return y})),n.d(t,"h",(function(){return v}));var r=n(0),o=n(6),i=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]-1&&this.subject.observers.splice(e,1),0===this.subject.observers.length&&this.subject.cancelCallback&&this.subject.cancelCallback().catch((function(e){}))},e}(),y=function(){function e(e){this.minimumLogLevel=e,this.outputConsole=console}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.a.Critical:case r.a.Error:this.outputConsole.error("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Warning:this.outputConsole.warn("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Information:this.outputConsole.info("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;default:this.outputConsole.log("["+(new Date).toISOString()+"] "+r.a[e]+": "+t)}},e}();function v(){var e="X-SignalR-User-Agent";return l.isNode&&(e="User-Agent"),[e,b(c,m(),E(),w())]}function b(e,t,n,r){var o="Microsoft SignalR/",i=e.split(".");return o+=i[0]+"."+i[1],o+=" ("+e+"; ",o+=t&&""!==t?t+"; ":"Unknown OS; ",o+=""+n,o+=r?"; "+r:"; Unknown Runtime Version",o+=")"}function m(){if(!l.isNode)return"";switch(e.platform){case"win32":return"Windows NT";case"darwin":return"macOS";case"linux":return"Linux";default:return e.platform}}function w(){if(l.isNode)return e.versions.node}function E(){return l.isNode?"NodeJS":"Browser"}}).call(this,n(14))},function(e,t,n){"use strict";n.r(t),n.d(t,"AbortError",(function(){return s})),n.d(t,"HttpError",(function(){return i})),n.d(t,"TimeoutError",(function(){return a})),n.d(t,"HttpClient",(function(){return l})),n.d(t,"HttpResponse",(function(){return u})),n.d(t,"DefaultHttpClient",(function(){return S})),n.d(t,"HubConnection",(function(){return O})),n.d(t,"HubConnectionState",(function(){return I})),n.d(t,"HubConnectionBuilder",(function(){return re})),n.d(t,"MessageType",(function(){return b})),n.d(t,"LogLevel",(function(){return f.a})),n.d(t,"HttpTransportType",(function(){return P})),n.d(t,"TransferFormat",(function(){return x})),n.d(t,"NullLogger",(function(){return $.a})),n.d(t,"JsonHubProtocol",(function(){return ee})),n.d(t,"Subject",(function(){return _})),n.d(t,"VERSION",(function(){return h.e}));var r,o=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=function(e){function t(t,n){var r=this,o=this.constructor.prototype;return(r=e.call(this,t)||this).statusCode=n,r.__proto__=o,r}return o(t,e),t}(Error),a=function(e){function t(t){void 0===t&&(t="A timeout occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return o(t,e),t}(Error),s=function(e){function t(t){void 0===t&&(t="An abort occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return o(t,e),t}(Error),c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=200&&o.status<300?n(new u(o.status,o.statusText,o.response||o.responseText)):r(new i(o.statusText,o.status))},o.onerror=function(){t.logger.log(f.a.Warning,"Error from HTTP request. "+o.status+": "+o.statusText+"."),r(new i(o.statusText,o.status))},o.ontimeout=function(){t.logger.log(f.a.Warning,"Timeout from HTTP request."),r(new a)},o.send(e.content||"")})):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t}(l),E=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),S=function(e){function t(t){var n=e.call(this)||this;if("undefined"!=typeof fetch||h.c.isNode)n.httpClient=new v(t);else{if("undefined"==typeof XMLHttpRequest)throw new Error("No usable HttpClient found.");n.httpClient=new w(t)}return n}return E(t,e),t.prototype.send=function(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new s):e.method?e.url?this.httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t.prototype.getCookieString=function(e){return this.httpClient.getCookieString(e)},t}(l),C=n(44);!function(e){e[e.Invocation=1]="Invocation",e[e.StreamItem=2]="StreamItem",e[e.Completion=3]="Completion",e[e.StreamInvocation=4]="StreamInvocation",e[e.CancelInvocation=5]="CancelInvocation",e[e.Ping=6]="Ping",e[e.Close=7]="Close"}(b||(b={}));var I,_=function(){function e(){this.observers=[]}return e.prototype.next=function(e){for(var t=0,n=this.observers;t0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0?[2,Promise.reject(new Error("Unable to connect to the server with any of the available transports. "+i.join(" ")))]:[2,Promise.reject(new Error("None of the transports supported by the client are supported by the server."))]}}))}))},e.prototype.constructTransport=function(e){switch(e){case P.WebSockets:if(!this.options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new Y(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.WebSocket,this.options.headers||{});case P.ServerSentEvents:if(!this.options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new H(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.EventSource,this.options.withCredentials,this.options.headers||{});case P.LongPolling:return new B(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.withCredentials,this.options.headers||{});default:throw new Error("Unknown transport: "+e+".")}},e.prototype.startTransport=function(e,t){var n=this;return this.transport.onreceive=this.onreceive,this.transport.onclose=function(e){return n.stopConnection(e)},this.transport.connect(e,t)},e.prototype.resolveTransportOrError=function(e,t,n){var r=P[e.transport];if(null==r)return this.logger.log(f.a.Debug,"Skipping transport '"+e.transport+"' because it is not supported by this client."),new Error("Skipping transport '"+e.transport+"' because it is not supported by this client.");if(!function(e,t){return!e||0!=(t&e)}(t,r))return this.logger.log(f.a.Debug,"Skipping transport '"+P[r]+"' because it was disabled by the client."),new Error("'"+P[r]+"' is disabled by the client.");if(!(e.transferFormats.map((function(e){return x[e]})).indexOf(n)>=0))return this.logger.log(f.a.Debug,"Skipping transport '"+P[r]+"' because it does not support the requested transfer format '"+x[n]+"'."),new Error("'"+P[r]+"' does not support "+x[n]+".");if(r===P.WebSockets&&!this.options.WebSocket||r===P.ServerSentEvents&&!this.options.EventSource)return this.logger.log(f.a.Debug,"Skipping transport '"+P[r]+"' because it is not supported in your environment.'"),new Error("'"+P[r]+"' is not supported in your environment.");this.logger.log(f.a.Debug,"Selecting transport '"+P[r]+"'.");try{return this.constructTransport(r)}catch(e){return e}},e.prototype.isITransport=function(e){return e&&"object"==typeof e&&"connect"in e},e.prototype.stopConnection=function(e){var t=this;if(this.logger.log(f.a.Debug,"HttpConnection.stopConnection("+e+") called while in state "+this.connectionState+"."),this.transport=void 0,e=this.stopError||e,this.stopError=void 0,"Disconnected"!==this.connectionState){if("Connecting"===this.connectionState)throw this.logger.log(f.a.Warning,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection is still in the connecting state."),new Error("HttpConnection.stopConnection("+e+") was called while the connection is still in the connecting state.");if("Disconnecting"===this.connectionState&&this.stopPromiseResolver(),e?this.logger.log(f.a.Error,"Connection disconnected with error '"+e+"'."):this.logger.log(f.a.Information,"Connection disconnected."),this.sendQueue&&(this.sendQueue.stop().catch((function(e){t.logger.log(f.a.Error,"TransportSendQueue.stop() threw error '"+e+"'.")})),this.sendQueue=void 0),this.connectionId=void 0,this.connectionState="Disconnected",this.connectionStarted){this.connectionStarted=!1;try{this.onclose&&this.onclose(e)}catch(t){this.logger.log(f.a.Error,"HttpConnection.onclose("+e+") threw error '"+t+"'.")}}}else this.logger.log(f.a.Debug,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection is already in the disconnected state.")},e.prototype.resolveUrl=function(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if(!h.c.isBrowser||!window.document)throw new Error("Cannot resolve '"+e+"'.");var t=window.document.createElement("a");return t.href=e,this.logger.log(f.a.Information,"Normalizing '"+e+"' to '"+t.href+"'."),t.href},e.prototype.resolveNegotiateUrl=function(e){var t=e.indexOf("?"),n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",-1===(n+=-1===t?"":e.substring(t)).indexOf("negotiateVersion")&&(n+=-1===t?"?":"&",n+="negotiateVersion="+this.negotiateVersion),n},e}();var G=function(){function e(e){this.transport=e,this.buffer=[],this.executing=!0,this.sendBufferedData=new Q,this.transportResult=new Q,this.sendLoopPromise=this.sendLoop()}return e.prototype.send=function(e){return this.bufferData(e),this.transportResult||(this.transportResult=new Q),this.transportResult.promise},e.prototype.stop=function(){return this.executing=!1,this.sendBufferedData.resolve(),this.sendLoopPromise},e.prototype.bufferData=function(e){if(this.buffer.length&&typeof this.buffer[0]!=typeof e)throw new Error("Expected data to be of type "+typeof this.buffer+" but was of type "+typeof e);this.buffer.push(e),this.sendBufferedData.resolve()},e.prototype.sendLoop=function(){return K(this,void 0,void 0,(function(){var t,n,r;return V(this,(function(o){switch(o.label){case 0:return[4,this.sendBufferedData.promise];case 1:if(o.sent(),!this.executing)return this.transportResult&&this.transportResult.reject("Connection stopped."),[3,6];this.sendBufferedData=new Q,t=this.transportResult,this.transportResult=void 0,n="string"==typeof this.buffer[0]?this.buffer.join(""):e.concatBuffers(this.buffer),this.buffer.length=0,o.label=2;case 2:return o.trys.push([2,4,,5]),[4,this.transport.send(n)];case 3:return o.sent(),t.resolve(),[3,5];case 4:return r=o.sent(),t.reject(r),[3,5];case 5:return[3,0];case 6:return[2]}}))}))},e.concatBuffers=function(e){for(var t=e.map((function(e){return e.byteLength})).reduce((function(e,t){return e+t})),n=new Uint8Array(t),r=0,o=0,i=e;o0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]-1&&this.subject.observers.splice(e,1),0===this.subject.observers.length&&this.subject.cancelCallback&&this.subject.cancelCallback().catch((function(e){}))},e}(),y=function(){function e(e){this.minimumLogLevel=e,this.outputConsole=console}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.a.Critical:case r.a.Error:this.outputConsole.error("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Warning:this.outputConsole.warn("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Information:this.outputConsole.info("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;default:this.outputConsole.log("["+(new Date).toISOString()+"] "+r.a[e]+": "+t)}},e}();function v(){var e="X-SignalR-User-Agent";return l.isNode&&(e="User-Agent"),[e,b(c,m(),E(),w())]}function b(e,t,n,r){var o="Microsoft SignalR/",i=e.split(".");return o+=i[0]+"."+i[1],o+=" ("+e+"; ",o+=t&&""!==t?t+"; ":"Unknown OS; ",o+=""+n,o+=r?"; "+r:"; Unknown Runtime Version",o+=")"}function m(){if(!l.isNode)return"";switch(e.platform){case"win32":return"Windows NT";case"darwin":return"macOS";case"linux":return"Linux";default:return e.platform}}function w(){if(l.isNode)return e.versions.node}function E(){return l.isNode?"NodeJS":"Browser"}}).call(this,n(14))},function(e,t,n){"use strict";n.r(t),n.d(t,"AbortError",(function(){return s})),n.d(t,"HttpError",(function(){return i})),n.d(t,"TimeoutError",(function(){return a})),n.d(t,"HttpClient",(function(){return l})),n.d(t,"HttpResponse",(function(){return u})),n.d(t,"DefaultHttpClient",(function(){return S})),n.d(t,"HubConnection",(function(){return O})),n.d(t,"HubConnectionState",(function(){return I})),n.d(t,"HubConnectionBuilder",(function(){return re})),n.d(t,"MessageType",(function(){return b})),n.d(t,"LogLevel",(function(){return f.a})),n.d(t,"HttpTransportType",(function(){return P})),n.d(t,"TransferFormat",(function(){return x})),n.d(t,"NullLogger",(function(){return $.a})),n.d(t,"JsonHubProtocol",(function(){return ee})),n.d(t,"Subject",(function(){return _})),n.d(t,"VERSION",(function(){return h.e}));var r,o=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=function(e){function t(t,n){var r=this,o=this.constructor.prototype;return(r=e.call(this,t)||this).statusCode=n,r.__proto__=o,r}return o(t,e),t}(Error),a=function(e){function t(t){void 0===t&&(t="A timeout occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return o(t,e),t}(Error),s=function(e){function t(t){void 0===t&&(t="An abort occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return o(t,e),t}(Error),c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=200&&o.status<300?n(new u(o.status,o.statusText,o.response||o.responseText)):r(new i(o.statusText,o.status))},o.onerror=function(){t.logger.log(f.a.Warning,"Error from HTTP request. "+o.status+": "+o.statusText+"."),r(new i(o.statusText,o.status))},o.ontimeout=function(){t.logger.log(f.a.Warning,"Timeout from HTTP request."),r(new a)},o.send(e.content||"")})):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t}(l),E=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),S=function(e){function t(t){var n=e.call(this)||this;if("undefined"!=typeof fetch||h.c.isNode)n.httpClient=new v(t);else{if("undefined"==typeof XMLHttpRequest)throw new Error("No usable HttpClient found.");n.httpClient=new w(t)}return n}return E(t,e),t.prototype.send=function(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new s):e.method?e.url?this.httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t.prototype.getCookieString=function(e){return this.httpClient.getCookieString(e)},t}(l),C=n(44);!function(e){e[e.Invocation=1]="Invocation",e[e.StreamItem=2]="StreamItem",e[e.Completion=3]="Completion",e[e.StreamInvocation=4]="StreamInvocation",e[e.CancelInvocation=5]="CancelInvocation",e[e.Ping=6]="Ping",e[e.Close=7]="Close"}(b||(b={}));var I,_=function(){function e(){this.observers=[]}return e.prototype.next=function(e){for(var t=0,n=this.observers;t0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0?[2,Promise.reject(new Error("Unable to connect to the server with any of the available transports. "+i.join(" ")))]:[2,Promise.reject(new Error("None of the transports supported by the client are supported by the server."))]}}))}))},e.prototype.constructTransport=function(e){switch(e){case P.WebSockets:if(!this.options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new Y(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.WebSocket,this.options.headers||{});case P.ServerSentEvents:if(!this.options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new H(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.EventSource,this.options.withCredentials,this.options.headers||{});case P.LongPolling:return new B(this.httpClient,this.accessTokenFactory,this.logger,this.options.logMessageContent||!1,this.options.withCredentials,this.options.headers||{});default:throw new Error("Unknown transport: "+e+".")}},e.prototype.startTransport=function(e,t){var n=this;return this.transport.onreceive=this.onreceive,this.transport.onclose=function(e){return n.stopConnection(e)},this.transport.connect(e,t)},e.prototype.resolveTransportOrError=function(e,t,n){var r=P[e.transport];if(null==r)return this.logger.log(f.a.Debug,"Skipping transport '"+e.transport+"' because it is not supported by this client."),new Error("Skipping transport '"+e.transport+"' because it is not supported by this client.");if(!function(e,t){return!e||0!=(t&e)}(t,r))return this.logger.log(f.a.Debug,"Skipping transport '"+P[r]+"' because it was disabled by the client."),new Error("'"+P[r]+"' is disabled by the client.");if(!(e.transferFormats.map((function(e){return x[e]})).indexOf(n)>=0))return this.logger.log(f.a.Debug,"Skipping transport '"+P[r]+"' because it does not support the requested transfer format '"+x[n]+"'."),new Error("'"+P[r]+"' does not support "+x[n]+".");if(r===P.WebSockets&&!this.options.WebSocket||r===P.ServerSentEvents&&!this.options.EventSource)return this.logger.log(f.a.Debug,"Skipping transport '"+P[r]+"' because it is not supported in your environment.'"),new Error("'"+P[r]+"' is not supported in your environment.");this.logger.log(f.a.Debug,"Selecting transport '"+P[r]+"'.");try{return this.constructTransport(r)}catch(e){return e}},e.prototype.isITransport=function(e){return e&&"object"==typeof e&&"connect"in e},e.prototype.stopConnection=function(e){var t=this;if(this.logger.log(f.a.Debug,"HttpConnection.stopConnection("+e+") called while in state "+this.connectionState+"."),this.transport=void 0,e=this.stopError||e,this.stopError=void 0,"Disconnected"!==this.connectionState){if("Connecting"===this.connectionState)throw this.logger.log(f.a.Warning,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection is still in the connecting state."),new Error("HttpConnection.stopConnection("+e+") was called while the connection is still in the connecting state.");if("Disconnecting"===this.connectionState&&this.stopPromiseResolver(),e?this.logger.log(f.a.Error,"Connection disconnected with error '"+e+"'."):this.logger.log(f.a.Information,"Connection disconnected."),this.sendQueue&&(this.sendQueue.stop().catch((function(e){t.logger.log(f.a.Error,"TransportSendQueue.stop() threw error '"+e+"'.")})),this.sendQueue=void 0),this.connectionId=void 0,this.connectionState="Disconnected",this.connectionStarted){this.connectionStarted=!1;try{this.onclose&&this.onclose(e)}catch(t){this.logger.log(f.a.Error,"HttpConnection.onclose("+e+") threw error '"+t+"'.")}}}else this.logger.log(f.a.Debug,"Call to HttpConnection.stopConnection("+e+") was ignored because the connection is already in the disconnected state.")},e.prototype.resolveUrl=function(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if(!h.c.isBrowser||!window.document)throw new Error("Cannot resolve '"+e+"'.");var t=window.document.createElement("a");return t.href=e,this.logger.log(f.a.Information,"Normalizing '"+e+"' to '"+t.href+"'."),t.href},e.prototype.resolveNegotiateUrl=function(e){var t=e.indexOf("?"),n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",-1===(n+=-1===t?"":e.substring(t)).indexOf("negotiateVersion")&&(n+=-1===t?"?":"&",n+="negotiateVersion="+this.negotiateVersion),n},e}();var G=function(){function e(e){this.transport=e,this.buffer=[],this.executing=!0,this.sendBufferedData=new Q,this.transportResult=new Q,this.sendLoopPromise=this.sendLoop()}return e.prototype.send=function(e){return this.bufferData(e),this.transportResult||(this.transportResult=new Q),this.transportResult.promise},e.prototype.stop=function(){return this.executing=!1,this.sendBufferedData.resolve(),this.sendLoopPromise},e.prototype.bufferData=function(e){if(this.buffer.length&&typeof this.buffer[0]!=typeof e)throw new Error("Expected data to be of type "+typeof this.buffer+" but was of type "+typeof e);this.buffer.push(e),this.sendBufferedData.resolve()},e.prototype.sendLoop=function(){return K(this,void 0,void 0,(function(){var t,n,r;return V(this,(function(o){switch(o.label){case 0:return[4,this.sendBufferedData.promise];case 1:if(o.sent(),!this.executing)return this.transportResult&&this.transportResult.reject("Connection stopped."),[3,6];this.sendBufferedData=new Q,t=this.transportResult,this.transportResult=void 0,n="string"==typeof this.buffer[0]?this.buffer.join(""):e.concatBuffers(this.buffer),this.buffer.length=0,o.label=2;case 2:return o.trys.push([2,4,,5]),[4,this.transport.send(n)];case 3:return o.sent(),t.resolve(),[3,5];case 4:return r=o.sent(),t.reject(r),[3,5];case 5:return[3,0];case 6:return[2]}}))}))},e.concatBuffers=function(e){for(var t=e.map((function(e){return e.byteLength})).reduce((function(e,t){return e+t})),n=new Uint8Array(t),r=0,o=0,i=e;o0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return r in e||(e[r]=[]),e}function u(e,t,n){var i=e;if(e instanceof Comment&&(c(i)&&c(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(s(i))throw new Error("Not implemented: moving existing logical children");var a=c(t);if(n0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=s,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return c(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=c,t.permuteLogicalChildren=function(e,t){var n=c(e);t.forEach((function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=s(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)})),t.forEach((function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):d(r,e)})),t.forEach((function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)})),t.forEach((function(e){n[e.toSiblingIndex]=e.moveRangeStart}))},t.getClosestDomElement=l},,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");return r(e,t)},t.setEventDispatcher=function(e){r=e}},,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(8),o=n(4),i=n(31),a=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions,domWrapper:i.domFunctions,setProfilingEnabled:a.setProfilingEnabled}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(26),o=n(27),i=n(13),a=n(30),u=n(19),s=n(8),c=n(5),l=document.createElement("template"),f=document.createElementNS("http://www.w3.org/2000/svg","g"),d={submit:!0},p={},h=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator((function(e,n,r,o){!function(e,t,n,r,o){d[e.type]&&e.preventDefault();var i={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};u.dispatchEvent(i,r.data)}(e,t.browserRendererId,n,r,o)})),s.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),p[e]=t},e.prototype.updateComponent=function(e,t,n,r){c.profileStart("updateComponent");var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var a=p[t];if(a){var u=i.getLogicalSiblingEnd(a);delete p[t],u?function(e,t){var n=i.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=i.getLogicalChildrenArray(n),o=r.indexOf(e)+1,a=r.indexOf(t),u=o;u<=a;u++)i.removeLogicalChild(n,o);e.textContent="!"}(a,u):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(a)}var s=i.getClosestDomElement(o).ownerDocument,l=s&&s.activeElement;this.applyEdits(e,t,o,0,n,r),l instanceof HTMLElement&&s&&s.activeElement!==l&&l.focus(),c.profileEnd("updateComponent")},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,a,u){for(var s,c=0,l=o,f=e.arrayBuilderSegmentReader,d=e.editReader,p=e.frameReader,h=f.values(a),m=f.offset(a),v=m+f.count(a),y=m;y0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>>0)}t.readInt32LE=function(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24},t.readUint32LE=i,t.readUint64LE=function(e,t){var n=i(e,t+4);if(n>o)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*r+i(e,t)},t.readLEB128=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},,,,,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{s(r.next(e))}catch(e){i(e)}}function u(e){try{s(r.throw(e))}catch(e){i(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,u)}s((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var a=n(3);n(23);var u=n(18),s=n(46),c=n(4),l=n(49),f=n(35),d=n(19),p=n(50),h=n(51),m=n(52),v=n(5),y=!1;function b(e){return r(this,void 0,void 0,(function(){var t,n,f,b,g,w,E,_=this;return o(this,(function(C){switch(C.label){case 0:if(y)throw new Error("Blazor has already started.");return y=!0,d.setEventDispatcher((function(e,t){return a.DotNet.invokeMethodAsync("Microsoft.AspNetCore.Components.WebAssembly","DispatchEvent",e,JSON.stringify(t))})),t=u.setPlatform(s.monoPlatform),window.Blazor.platform=t,window.Blazor._internal.renderBatch=function(e,t){v.profileStart("renderBatch"),c.renderBatch(e,new l.SharedMemoryRenderBatch(t)),v.profileEnd("renderBatch")},n=window.Blazor._internal.navigationManager.getBaseURI,f=window.Blazor._internal.navigationManager.getLocationHref,window.Blazor._internal.navigationManager.getUnmarshalledBaseURI=function(){return BINDING.js_string_to_mono_string(n())},window.Blazor._internal.navigationManager.getUnmarshalledLocationHref=function(){return BINDING.js_string_to_mono_string(f())},window.Blazor._internal.navigationManager.listenForNavigationEvents((function(e,t){return r(_,void 0,void 0,(function(){return o(this,(function(n){switch(n.label){case 0:return[4,a.DotNet.invokeMethodAsync("Microsoft.AspNetCore.Components.WebAssembly","NotifyLocationChanged",e,t)];case 1:return n.sent(),[2]}}))}))})),[4,m.BootConfigResult.initAsync()];case 1:return b=C.sent(),[4,Promise.all([p.WebAssemblyResourceLoader.initAsync(b.bootConfig,e||{}),h.WebAssemblyConfigLoader.initAsync(b)])];case 2:g=i.apply(void 0,[C.sent(),1]),w=g[0],C.label=3;case 3:return C.trys.push([3,5,,6]),[4,t.start(w)];case 4:return C.sent(),[3,6];case 5:throw E=C.sent(),new Error("Failed to start platform. Reason: "+E);case 6:return t.callEntryPoint(w.bootConfig.entryAssembly),[2]}}))}))}window.Blazor.start=b,f.shouldAutoStart()&&b().catch((function(e){"undefined"!=typeof Module&&Module.printErr?Module.printErr(e):console.error(e)}))},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{s(r.next(e))}catch(e){i(e)}}function u(e){try{s(r.throw(e))}catch(e){i(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,u)}s((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>2]}t.monoPlatform={start:function(e){return new Promise((function(t,n){var f,d;u.attachDebuggerHotkey(e),l.initializeProfiling((function(e){v("Microsoft.AspNetCore.Components","Microsoft.AspNetCore.Components.Profiling.WebAssemblyComponentsProfiling","SetCapturing")(e)})),window.Browser={init:function(){}},f=function(){window.Module=function(e,t,n){var l=this,f=e.bootConfig.resources,d=window.Module||{},p=["DEBUGGING ENABLED"];d.print=function(e){return p.indexOf(e)<0&&console.log(e)},d.printErr=function(e){console.error(e),s.showErrorNotification()},d.preRun=d.preRun||[],d.postRun=d.postRun||[],d.preloadPlugins=[];var m,b=e.loadResources(f.assembly,(function(e){return"_framework/"+e}),"assembly"),g=e.loadResources(f.pdb||{},(function(e){return"_framework/"+e}),"pdb"),w=e.loadResource("dotnet.wasm","_framework/dotnet.wasm",e.bootConfig.resources.runtime["dotnet.wasm"],"dotnetwasm");return e.bootConfig.resources.runtime.hasOwnProperty("dotnet.timezones.dat")&&(m=e.loadResource("dotnet.timezones.dat","_framework/dotnet.timezones.dat",e.bootConfig.resources.runtime["dotnet.timezones.dat"],"timezonedata")),d.instantiateWasm=function(e,t){return r(l,void 0,void 0,(function(){var n,r;return o(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),[4,w];case 1:return[4,y(o.sent(),e)];case 2:return n=o.sent(),[3,4];case 3:throw r=o.sent(),d.printErr(r),r;case 4:return t(n),[2]}}))})),[]},d.preRun.push((function(){i=cwrap("mono_wasm_add_assembly",null,["string","number","number"]),cwrap("mono_wasm_string_get_utf8","number",["number"]),MONO.loaded_files=[],m&&function(e){r(this,void 0,void 0,(function(){var t,n;return o(this,(function(r){switch(r.label){case 0:return t="blazor:timezonedata",addRunDependency(t),[4,e.response];case 1:return[4,r.sent().arrayBuffer()];case 2:return n=r.sent(),c.loadTimezoneData(n),removeRunDependency(t),[2]}}))}))}(m),b.forEach((function(e){return E(e,function(e,t){var n=e.lastIndexOf(".");if(n<0)throw new Error("No extension to replace in '"+e+"'");return e.substr(0,n)+t}(e.name,".dll"))})),g.forEach((function(e){return E(e,e.name)})),window.Blazor._internal.dotNetCriticalError=function(e){d.printErr(BINDING.conv_string(e)||"(null)")},window.Blazor._internal.getSatelliteAssemblies=function(t){var n=BINDING.mono_array_to_js_array(t),i=e.bootConfig.resources.satelliteResources;if(i){var a=Promise.all(n.filter((function(e){return i.hasOwnProperty(e)})).map((function(t){return e.loadResources(i[t],(function(e){return"_framework/"+e}),"assembly")})).reduce((function(e,t){return e.concat(t)}),new Array).map((function(e){return r(l,void 0,void 0,(function(){return o(this,(function(t){switch(t.label){case 0:return[4,e.response];case 1:return[2,t.sent().arrayBuffer()]}}))}))})));return BINDING.js_to_mono_obj(a.then((function(e){return e.length&&(window.Blazor._internal.readSatelliteAssemblies=function(){for(var t=BINDING.mono_obj_array_new(e.length),n=0;n>1];var n},readInt32Field:function(e,t){return p(e+(t||0))},readUint64Field:function(e,t){return function(e){var t=e>>2,n=Module.HEAPU32[t+1];if(n>d)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*f+Module.HEAPU32[t]}(e+(t||0))},readFloatField:function(e,t){return n=e+(t||0),Module.HEAPF32[n>>2];var n},readObjectField:function(e,t){return p(e+(t||0))},readStringField:function(e,t,n){var r=p(e+(t||0));if(0===r)return null;if(n){var o=BINDING.unbox_mono_obj(r);return"boolean"==typeof o?o?"":null:o}return BINDING.conv_string(r)},readStructField:function(e,t){return e+(t||0)}};var h=document.createElement("a");function m(e){return e+12}function v(e,t,n){var r="["+e+"] "+t+":"+n;return BINDING.bind_static_method(r)}function y(e,t){return r(this,void 0,void 0,(function(){var n,r;return o(this,(function(o){switch(o.label){case 0:if("function"!=typeof WebAssembly.instantiateStreaming)return[3,4];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,WebAssembly.instantiateStreaming(e.response,t)];case 2:return[2,o.sent().instance];case 3:return n=o.sent(),console.info("Streaming compilation failed. Falling back to ArrayBuffer instantiation. ",n),[3,4];case 4:return[4,e.response.then((function(e){return e.arrayBuffer()}))];case 5:return r=o.sent(),[4,WebAssembly.instantiate(r,t)];case 6:return[2,o.sent().instance]}}))}))}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=window.chrome&&navigator.userAgent.indexOf("Edge")<0,o=!1;function i(){return o&&r}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){o=!!e.bootConfig.resources.pdb;var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",(function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(o?r?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Microsoft Edge (80+), or Google Chrome, are supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))}))}},function(e,t,n){"use strict";var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var i=n(33),a=n(34);t.loadTimezoneData=function(e){var t,n,u=new Uint8Array(e),s=i.readInt32LE(u,0);u=u.slice(4);var c=a.decodeUtf8(u.slice(0,s)),l=JSON.parse(c);u=u.slice(s),Module.FS_createPath("/","zoneinfo",!0,!0),new Set(l.map((function(e){return e[0].split("/")[0]}))).forEach((function(e){return Module.FS_createPath("/zoneinfo",e,!0,!0)}));try{for(var f=r(l),d=f.next();!d.done;d=f.next()){var p=o(d.value,2),h=p[0],m=p[1],v=u.slice(0,m);Module.FS_createDataFile("/zoneinfo/"+h,null,v,!0,!0,!0),u=u.slice(m)}}catch(e){t={error:e}}finally{try{d&&!d.done&&(n=f.return)&&n.call(f)}finally{if(t)throw t.error}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=i,this.arrayBuilderSegmentReader=a,this.diffReader=u,this.editReader=s,this.frameReader=c}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,i.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*i.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*i.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return l(e,t,u.structLength)},e.prototype.referenceFramesEntry=function(e,t){return l(e,t,c.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=l(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=l(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var i={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},a={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},u={structLength:4+a.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return l(e,t,s.structLength)}},s={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},c={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24,!0)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function l(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{s(r.next(e))}catch(e){i(e)}}function u(e){try{s(r.throw(e))}catch(e){i(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,u)}s((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return r in e||(e[r]=[]),e}function u(e,t,n){var i=e;if(e instanceof Comment&&(c(i)&&c(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(s(i))throw new Error("Not implemented: moving existing logical children");var a=c(t);if(n0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=s,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return c(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=c,t.permuteLogicalChildren=function(e,t){var n=c(e);t.forEach((function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=s(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)})),t.forEach((function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):d(r,e)})),t.forEach((function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)})),t.forEach((function(e){n[e.toSiblingIndex]=e.moveRangeStart}))},t.getClosestDomElement=l},,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");return r(e,t)},t.setEventDispatcher=function(e){r=e}},,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(8),o=n(4),i=n(31),a=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions,domWrapper:i.domFunctions,setProfilingEnabled:a.setProfilingEnabled}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(26),o=n(27),i=n(13),a=n(30),u=n(19),s=n(8),c=n(5),l=document.createElement("template"),f=document.createElementNS("http://www.w3.org/2000/svg","g"),d={submit:!0},p={},h=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator((function(e,n,r,o){!function(e,t,n,r,o){d[e.type]&&e.preventDefault();var i={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};u.dispatchEvent(i,r.data)}(e,t.browserRendererId,n,r,o)})),s.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),p[e]=t},e.prototype.updateComponent=function(e,t,n,r){c.profileStart("updateComponent");var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var a=p[t];if(a){var u=i.getLogicalSiblingEnd(a);delete p[t],u?function(e,t){var n=i.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=i.getLogicalChildrenArray(n),o=r.indexOf(e)+1,a=r.indexOf(t),u=o;u<=a;u++)i.removeLogicalChild(n,o);e.textContent="!"}(a,u):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(a)}var s=i.getClosestDomElement(o).ownerDocument,l=s&&s.activeElement;this.applyEdits(e,t,o,0,n,r),l instanceof HTMLElement&&s&&s.activeElement!==l&&l.focus(),c.profileEnd("updateComponent")},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,a,u){for(var s,c=0,l=o,f=e.arrayBuilderSegmentReader,d=e.editReader,p=e.frameReader,h=f.values(a),m=f.offset(a),v=m+f.count(a),y=m;y0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>>0)}t.readInt32LE=function(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24},t.readUint32LE=i,t.readUint64LE=function(e,t){var n=i(e,t+4);if(n>o)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*r+i(e,t)},t.readLEB128=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},,,,,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{s(r.next(e))}catch(e){i(e)}}function u(e){try{s(r.throw(e))}catch(e){i(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,u)}s((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var a=n(3);n(23);var u=n(18),s=n(46),c=n(4),l=n(49),f=n(35),d=n(19),p=n(50),h=n(51),m=n(52),v=n(5),y=!1;function b(e){return r(this,void 0,void 0,(function(){var t,n,f,b,g,w,E,_=this;return o(this,(function(C){switch(C.label){case 0:if(y)throw new Error("Blazor has already started.");return y=!0,d.setEventDispatcher((function(e,t){return a.DotNet.invokeMethodAsync("Microsoft.AspNetCore.Components.WebAssembly","DispatchEvent",e,JSON.stringify(t))})),t=u.setPlatform(s.monoPlatform),window.Blazor.platform=t,window.Blazor._internal.renderBatch=function(e,t){v.profileStart("renderBatch"),c.renderBatch(e,new l.SharedMemoryRenderBatch(t)),v.profileEnd("renderBatch")},n=window.Blazor._internal.navigationManager.getBaseURI,f=window.Blazor._internal.navigationManager.getLocationHref,window.Blazor._internal.navigationManager.getUnmarshalledBaseURI=function(){return BINDING.js_string_to_mono_string(n())},window.Blazor._internal.navigationManager.getUnmarshalledLocationHref=function(){return BINDING.js_string_to_mono_string(f())},window.Blazor._internal.navigationManager.listenForNavigationEvents((function(e,t){return r(_,void 0,void 0,(function(){return o(this,(function(n){switch(n.label){case 0:return[4,a.DotNet.invokeMethodAsync("Microsoft.AspNetCore.Components.WebAssembly","NotifyLocationChanged",e,t)];case 1:return n.sent(),[2]}}))}))})),[4,m.BootConfigResult.initAsync()];case 1:return b=C.sent(),[4,Promise.all([p.WebAssemblyResourceLoader.initAsync(b.bootConfig,e||{}),h.WebAssemblyConfigLoader.initAsync(b)])];case 2:g=i.apply(void 0,[C.sent(),1]),w=g[0],C.label=3;case 3:return C.trys.push([3,5,,6]),[4,t.start(w)];case 4:return C.sent(),[3,6];case 5:throw E=C.sent(),new Error("Failed to start platform. Reason: "+E);case 6:return t.callEntryPoint(w.bootConfig.entryAssembly),[2]}}))}))}window.Blazor.start=b,f.shouldAutoStart()&&b().catch((function(e){"undefined"!=typeof Module&&Module.printErr?Module.printErr(e):console.error(e)}))},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{s(r.next(e))}catch(e){i(e)}}function u(e){try{s(r.throw(e))}catch(e){i(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,u)}s((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>2]}t.monoPlatform={start:function(e){return new Promise((function(t,n){var f,d;u.attachDebuggerHotkey(e),l.initializeProfiling((function(e){v("Microsoft.AspNetCore.Components","Microsoft.AspNetCore.Components.Profiling.WebAssemblyComponentsProfiling","SetCapturing")(e)})),window.Browser={init:function(){}},f=function(){window.Module=function(e,t,n){var l=this,f=e.bootConfig.resources,d=window.Module||{},p=["DEBUGGING ENABLED"];d.print=function(e){return p.indexOf(e)<0&&console.log(e)},d.printErr=function(e){console.error(e),s.showErrorNotification()},d.preRun=d.preRun||[],d.postRun=d.postRun||[],d.preloadPlugins=[];var m,b=e.loadResources(f.assembly,(function(e){return"_framework/"+e}),"assembly"),g=e.loadResources(f.pdb||{},(function(e){return"_framework/"+e}),"pdb"),w=e.loadResource("dotnet.wasm","_framework/dotnet.wasm",e.bootConfig.resources.runtime["dotnet.wasm"],"dotnetwasm");return e.bootConfig.resources.runtime.hasOwnProperty("dotnet.timezones.dat")&&(m=e.loadResource("dotnet.timezones.dat","_framework/dotnet.timezones.dat",e.bootConfig.resources.runtime["dotnet.timezones.dat"],"timezonedata")),d.instantiateWasm=function(e,t){return r(l,void 0,void 0,(function(){var n,r;return o(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),[4,w];case 1:return[4,y(o.sent(),e)];case 2:return n=o.sent(),[3,4];case 3:throw r=o.sent(),d.printErr(r),r;case 4:return t(n),[2]}}))})),[]},d.preRun.push((function(){i=cwrap("mono_wasm_add_assembly",null,["string","number","number"]),cwrap("mono_wasm_string_get_utf8","number",["number"]),MONO.loaded_files=[],m&&function(e){r(this,void 0,void 0,(function(){var t,n;return o(this,(function(r){switch(r.label){case 0:return t="blazor:timezonedata",addRunDependency(t),[4,e.response];case 1:return[4,r.sent().arrayBuffer()];case 2:return n=r.sent(),c.loadTimezoneData(n),removeRunDependency(t),[2]}}))}))}(m),b.forEach((function(e){return E(e,function(e,t){var n=e.lastIndexOf(".");if(n<0)throw new Error("No extension to replace in '"+e+"'");return e.substr(0,n)+t}(e.name,".dll"))})),g.forEach((function(e){return E(e,e.name)})),window.Blazor._internal.dotNetCriticalError=function(e){d.printErr(BINDING.conv_string(e)||"(null)")},window.Blazor._internal.getSatelliteAssemblies=function(t){var n=BINDING.mono_array_to_js_array(t),i=e.bootConfig.resources.satelliteResources;if(i){var a=Promise.all(n.filter((function(e){return i.hasOwnProperty(e)})).map((function(t){return e.loadResources(i[t],(function(e){return"_framework/"+e}),"assembly")})).reduce((function(e,t){return e.concat(t)}),new Array).map((function(e){return r(l,void 0,void 0,(function(){return o(this,(function(t){switch(t.label){case 0:return[4,e.response];case 1:return[2,t.sent().arrayBuffer()]}}))}))})));return BINDING.js_to_mono_obj(a.then((function(e){return e.length&&(window.Blazor._internal.readSatelliteAssemblies=function(){for(var t=BINDING.mono_obj_array_new(e.length),n=0;n>1];var n},readInt32Field:function(e,t){return p(e+(t||0))},readUint64Field:function(e,t){return function(e){var t=e>>2,n=Module.HEAPU32[t+1];if(n>d)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*f+Module.HEAPU32[t]}(e+(t||0))},readFloatField:function(e,t){return n=e+(t||0),Module.HEAPF32[n>>2];var n},readObjectField:function(e,t){return p(e+(t||0))},readStringField:function(e,t,n){var r=p(e+(t||0));if(0===r)return null;if(n){var o=BINDING.unbox_mono_obj(r);return"boolean"==typeof o?o?"":null:o}return BINDING.conv_string(r)},readStructField:function(e,t){return e+(t||0)}};var h=document.createElement("a");function m(e){return e+12}function v(e,t,n){var r="["+e+"] "+t+":"+n;return BINDING.bind_static_method(r)}function y(e,t){return r(this,void 0,void 0,(function(){var n,r;return o(this,(function(o){switch(o.label){case 0:if("function"!=typeof WebAssembly.instantiateStreaming)return[3,4];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,WebAssembly.instantiateStreaming(e.response,t)];case 2:return[2,o.sent().instance];case 3:return n=o.sent(),console.info("Streaming compilation failed. Falling back to ArrayBuffer instantiation. ",n),[3,4];case 4:return[4,e.response.then((function(e){return e.arrayBuffer()}))];case 5:return r=o.sent(),[4,WebAssembly.instantiate(r,t)];case 6:return[2,o.sent().instance]}}))}))}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=window.chrome&&navigator.userAgent.indexOf("Edge")<0,o=!1;function i(){return o&&r}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){o=!!e.bootConfig.resources.pdb;var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",(function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(o?r?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Microsoft Edge (80+), or Google Chrome, are supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))}))}},function(e,t,n){"use strict";var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var i=n(33),a=n(34);t.loadTimezoneData=function(e){var t,n,u=new Uint8Array(e),s=i.readInt32LE(u,0);u=u.slice(4);var c=a.decodeUtf8(u.slice(0,s)),l=JSON.parse(c);u=u.slice(s),Module.FS_createPath("/","zoneinfo",!0,!0),new Set(l.map((function(e){return e[0].split("/")[0]}))).forEach((function(e){return Module.FS_createPath("/zoneinfo",e,!0,!0)}));try{for(var f=r(l),d=f.next();!d.done;d=f.next()){var p=o(d.value,2),h=p[0],m=p[1],v=u.slice(0,m);Module.FS_createDataFile("/zoneinfo/"+h,null,v,!0,!0,!0),u=u.slice(m)}}catch(e){t={error:e}}finally{try{d&&!d.done&&(n=f.return)&&n.call(f)}finally{if(t)throw t.error}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=i,this.arrayBuilderSegmentReader=a,this.diffReader=u,this.editReader=s,this.frameReader=c}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,i.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*i.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*i.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return l(e,t,u.structLength)},e.prototype.referenceFramesEntry=function(e,t){return l(e,t,c.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=l(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=l(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var i={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},a={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},u={structLength:4+a.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return l(e,t,s.structLength)}},s={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},c={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24,!0)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function l(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{s(r.next(e))}catch(e){i(e)}}function u(e){try{s(r.throw(e))}catch(e){i(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,u)}s((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(i){return function(u){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1] Date: Wed, 1 Jul 2020 22:00:16 +0000 Subject: [PATCH 078/100] Update dependencies from https://github.com/dotnet/efcore build 20200701.1 (#23576) Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20330.1 -> To Version 5.0.0-preview.8.20351.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2e6048a4b7..5ef5ce455b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 4795eee89fd67a05ae3aa288509c57200f0d7c89 + 928e87b18d8c0e72884752dc7b84ffa97325f1ac - + https://github.com/dotnet/efcore - 4795eee89fd67a05ae3aa288509c57200f0d7c89 + 928e87b18d8c0e72884752dc7b84ffa97325f1ac - + https://github.com/dotnet/efcore - 4795eee89fd67a05ae3aa288509c57200f0d7c89 + 928e87b18d8c0e72884752dc7b84ffa97325f1ac - + https://github.com/dotnet/efcore - 4795eee89fd67a05ae3aa288509c57200f0d7c89 + 928e87b18d8c0e72884752dc7b84ffa97325f1ac - + https://github.com/dotnet/efcore - 4795eee89fd67a05ae3aa288509c57200f0d7c89 + 928e87b18d8c0e72884752dc7b84ffa97325f1ac - + https://github.com/dotnet/efcore - 4795eee89fd67a05ae3aa288509c57200f0d7c89 + 928e87b18d8c0e72884752dc7b84ffa97325f1ac - + https://github.com/dotnet/efcore - 4795eee89fd67a05ae3aa288509c57200f0d7c89 + 928e87b18d8c0e72884752dc7b84ffa97325f1ac https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 07bdb0e8d1..9ef8dac65b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.8.20330.1 - 5.0.0-preview.8.20330.1 - 5.0.0-preview.8.20330.1 - 5.0.0-preview.8.20330.1 - 5.0.0-preview.8.20330.1 - 5.0.0-preview.8.20330.1 - 5.0.0-preview.8.20330.1 + 5.0.0-preview.8.20351.1 + 5.0.0-preview.8.20351.1 + 5.0.0-preview.8.20351.1 + 5.0.0-preview.8.20351.1 + 5.0.0-preview.8.20351.1 + 5.0.0-preview.8.20351.1 + 5.0.0-preview.8.20351.1 - + From fb671009ebb91f088f55c17dca2bcbd4378544f8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2020 02:53:55 +0000 Subject: [PATCH 081/100] Update dependencies from https://github.com/dotnet/efcore build 20200701.2 (#23593) Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20351.1 -> To Version 5.0.0-preview.8.20351.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5ef5ce455b..bbdb4a4c0f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - 928e87b18d8c0e72884752dc7b84ffa97325f1ac + e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 - + https://github.com/dotnet/efcore - 928e87b18d8c0e72884752dc7b84ffa97325f1ac + e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 - + https://github.com/dotnet/efcore - 928e87b18d8c0e72884752dc7b84ffa97325f1ac + e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 - + https://github.com/dotnet/efcore - 928e87b18d8c0e72884752dc7b84ffa97325f1ac + e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 - + https://github.com/dotnet/efcore - 928e87b18d8c0e72884752dc7b84ffa97325f1ac + e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 - + https://github.com/dotnet/efcore - 928e87b18d8c0e72884752dc7b84ffa97325f1ac + e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 - + https://github.com/dotnet/efcore - 928e87b18d8c0e72884752dc7b84ffa97325f1ac + e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 9ef8dac65b..050be0ff2e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.8.20351.1 - 5.0.0-preview.8.20351.1 - 5.0.0-preview.8.20351.1 - 5.0.0-preview.8.20351.1 - 5.0.0-preview.8.20351.1 - 5.0.0-preview.8.20351.1 - 5.0.0-preview.8.20351.1 + 5.0.0-preview.8.20351.2 + 5.0.0-preview.8.20351.2 + 5.0.0-preview.8.20351.2 + 5.0.0-preview.8.20351.2 + 5.0.0-preview.8.20351.2 + 5.0.0-preview.8.20351.2 + 5.0.0-preview.8.20351.2 - + https://github.com/dotnet/runtime - 2d0249e7ae75647c313623b7322cd71a72870deb + 719c58c88dc22fe07bcb64f07ba5a74cc10d274c - + https://github.com/dotnet/runtime - 2d0249e7ae75647c313623b7322cd71a72870deb + 719c58c88dc22fe07bcb64f07ba5a74cc10d274c - + https://github.com/dotnet/runtime - 2d0249e7ae75647c313623b7322cd71a72870deb + 719c58c88dc22fe07bcb64f07ba5a74cc10d274c https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index 050be0ff2e..555ae79bc1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,69 +66,69 @@ 3.7.0-4.20319.6 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 - 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20330.14 + 5.0.0-preview.8.20351.9 3.2.0 From b4a37194f507e6edee649e65411968e87092f87e Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 2 Jul 2020 07:02:27 -0700 Subject: [PATCH 083/100] Skip component governance for linux musl x64 (#23592) * Skip component governance for linux musl x64 * Use parameters * jazz --- .azure/pipelines/ci.yml | 1 + .azure/pipelines/jobs/default-build.yml | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index 86946e879b..5f44f14fc3 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -449,6 +449,7 @@ stages: $(_InternalRuntimeDownloadArgs) installNodeJs: false installJdk: false + skipComponentGovernanceDetection: true artifacts: - name: Linux_musl_x64_Logs path: artifacts/log/ diff --git a/.azure/pipelines/jobs/default-build.yml b/.azure/pipelines/jobs/default-build.yml index 57c61890a5..f851f512f2 100644 --- a/.azure/pipelines/jobs/default-build.yml +++ b/.azure/pipelines/jobs/default-build.yml @@ -35,7 +35,8 @@ # Specifies what directory to run build.sh/cmd # buildScript: string # Specifies the build script to run. Defaults to build.sh or build.cmd. - +# skipComponentGovernanceDetection: boolean +# Determines if component governance detection can be skipped # # See https://docs.microsoft.com/en-us/vsts/pipelines/yaml-schema for details # @@ -60,6 +61,7 @@ parameters: installJdk: true timeoutInMinutes: 180 useHostedUbuntu: true + skipComponentGovernanceDetection: false # We need longer than the default amount of 5 minutes to upload our logs/artifacts. (We currently take around 5 mins in the best case). # This makes sure we have time to upload everything in the case of a build timeout - really important for investigating a build @@ -240,7 +242,7 @@ jobs: continueOnError: true condition: always() - - ${{ if and(startsWith(parameters.jobDisplayName, 'Build:'), ne(variables['skipComponentGovernanceDetection'], 'true'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if and(startsWith(parameters.jobDisplayName, 'Build:'), ne(parameters.skipComponentGovernanceDetection, 'true'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 condition: and(succeeded(), ne(variables['CG_RAN'], 'true')) displayName: 'Component Detection' From dcd32c0d14e1745eebf737bf9f948de309e02027 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 2 Jul 2020 09:22:56 -0700 Subject: [PATCH 084/100] Quarantine tests (#23598) * Quarantine tests * Quarantine shutdowntest --- src/Components/test/E2ETest/Tests/BindTest.cs | 2 ++ .../test/E2ETest/Tests/ErrorNotificationTest.cs | 2 ++ src/Components/test/E2ETest/Tests/RoutingTest.cs | 9 +++++++-- src/Hosting/test/FunctionalTests/ShutdownTests.cs | 1 + 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Components/test/E2ETest/Tests/BindTest.cs b/src/Components/test/E2ETest/Tests/BindTest.cs index 47f24f7c4b..d281f0c223 100644 --- a/src/Components/test/E2ETest/Tests/BindTest.cs +++ b/src/Components/test/E2ETest/Tests/BindTest.cs @@ -7,6 +7,7 @@ using BasicTestApp; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Testing; using Moq; using OpenQA.Selenium; using OpenQA.Selenium.Support.UI; @@ -506,6 +507,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")] public void CanBindTextboxNullableDouble() { var target = Browser.FindElement(By.Id("textbox-nullable-double")); diff --git a/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs b/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs index 1076e18832..bdac8d5ba4 100644 --- a/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs +++ b/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs @@ -6,6 +6,7 @@ using BasicTestApp; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Testing; using OpenQA.Selenium; using Xunit; using Xunit.Abstractions; @@ -50,6 +51,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")] public void ShowsErrorNotification_OnError_Reload() { var causeErrorButton = Browser.Exists(By.Id("throw-simple-exception")); diff --git a/src/Components/test/E2ETest/Tests/RoutingTest.cs b/src/Components/test/E2ETest/Tests/RoutingTest.cs index 8d9c4b45ea..29fec5e599 100644 --- a/src/Components/test/E2ETest/Tests/RoutingTest.cs +++ b/src/Components/test/E2ETest/Tests/RoutingTest.cs @@ -9,6 +9,7 @@ using BasicTestApp.RouterTest; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Testing; using OpenQA.Selenium; using OpenQA.Selenium.Interactions; using Xunit; @@ -479,14 +480,18 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests Browser.Equal(0, () => BrowserScrollY); } + [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")] + public void PreventDefault_CanBlockNavigation_ForInternalNavigation_PreventDefaultTarget() + => PreventDefault_CanBlockNavigation("internal", "target"); + [Theory] [InlineData("external", "ancestor")] [InlineData("external", "target")] [InlineData("external", "descendant")] [InlineData("internal", "ancestor")] - [InlineData("internal", "target")] [InlineData("internal", "descendant")] - public void PreventDefault_CanBlockNavigation(string navigationType, string whereToPreventDefault) + public virtual void PreventDefault_CanBlockNavigation(string navigationType, string whereToPreventDefault) { SetUrlViaPushState("/PreventDefaultCases"); var app = Browser.MountTestComponent(); diff --git a/src/Hosting/test/FunctionalTests/ShutdownTests.cs b/src/Hosting/test/FunctionalTests/ShutdownTests.cs index 8d0c8da6b2..ca689f8092 100644 --- a/src/Hosting/test/FunctionalTests/ShutdownTests.cs +++ b/src/Hosting/test/FunctionalTests/ShutdownTests.cs @@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.Hosting.FunctionalTests public ShutdownTests(ITestOutputHelper output) : base(output) { } [ConditionalFact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23610")] [OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ShutdownTestRun() From b7d9e8cfea97c9a3e6df871666d489556e2a3d0b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 2 Jul 2020 10:29:26 -0700 Subject: [PATCH 085/100] FIxup2 (#23618) --- .../Wasm.Performance/Driver/Wasm.Performance.Driver.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 8172295228..66aea279ee 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj +++ b/src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj @@ -8,8 +8,7 @@ false true - - linux-x64 + linux-x64 From a729c4230eefd4b5c3e21f9496de608cd25a72b8 Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Thu, 2 Jul 2020 11:48:34 -0700 Subject: [PATCH 086/100] InputRadio component with form support (#23415) * Started on InputRadio forms component. * Added E2E test for InputRadio. * Added docstring for InputRadio. * Changed value to be serialized using BindConverter. * Added InputChoice for choice-based inputs. InputChoice contains checks for valid choice types that used to exist in InputSelect. Both InputSelect and InputRadio now derive from InputChoice and thus also contain those checks. * Added InputRadioGroup. * Small fix. * Removed InputChoice, cleaned up. * Added internal access modifier to InputExtensions. * Small improvements. * Updated an outdated exception message. * Updated test to reflect updated exception message. * Improved API to enforce InputRadioGroup. * Added support for InputSelect int and Guid bindings. * Changed validation CSS classes to influence InputRadio components. --- ...ft.AspNetCore.Components.Web.netcoreapp.cs | 33 ++++- ...spNetCore.Components.Web.netstandard2.0.cs | 25 +++- src/Components/Web/src/Forms/InputBase.cs | 4 +- src/Components/Web/src/Forms/InputDate.cs | 2 +- .../Web/src/Forms/InputExtensions.cs | 35 +++++ src/Components/Web/src/Forms/InputNumber.cs | 2 +- src/Components/Web/src/Forms/InputRadio.cs | 82 +++++++++++ .../Web/src/Forms/InputRadioContext.cs | 64 ++++++++ .../Web/src/Forms/InputRadioGroup.cs | 57 ++++++++ src/Components/Web/src/Forms/InputSelect.cs | 31 +--- .../Web/src/Properties/AssemblyInfo.cs | 1 + .../Web/test/Forms/InputRadioTest.cs | 138 ++++++++++++++++++ .../Web/test/Forms/InputSelectTest.cs | 90 ++++++++++++ .../test/E2ETest/Tests/FormsTest.cs | 62 ++++++++ .../TypicalValidationComponent.razor | 42 ++++++ 15 files changed, 629 insertions(+), 39 deletions(-) create mode 100644 src/Components/Web/src/Forms/InputExtensions.cs create mode 100644 src/Components/Web/src/Forms/InputRadio.cs create mode 100644 src/Components/Web/src/Forms/InputRadioContext.cs create mode 100644 src/Components/Web/src/Forms/InputRadioGroup.cs create mode 100644 src/Components/Web/test/Forms/InputRadioTest.cs diff --git a/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netcoreapp.cs b/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netcoreapp.cs index 0f31f41fc1..795dbe6ea3 100644 --- a/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netcoreapp.cs +++ b/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netcoreapp.cs @@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Components.Forms protected TValue CurrentValue { get { throw null; } set { } } protected string? CurrentValueAsString { get { throw null; } set { } } protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - protected Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + protected internal Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } [Microsoft.AspNetCore.Components.ParameterAttribute] [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] [System.Diagnostics.CodeAnalysis.AllowNullAttribute] @@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Components.Forms [Microsoft.AspNetCore.Components.ParameterAttribute] public System.Linq.Expressions.Expression>? ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected virtual void Dispose(bool disposing) { } - protected virtual string? FormatValueAsString(TValue value) { throw null; } + protected virtual string? FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; } public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } void System.IDisposable.Dispose() { } protected abstract bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage); @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Components.Forms [Microsoft.AspNetCore.Components.ParameterAttribute] public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - protected override string FormatValueAsString(TValue value) { throw null; } + protected override string FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; } protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; } } public partial class InputNumber : Microsoft.AspNetCore.Components.Forms.InputBase @@ -97,9 +97,34 @@ namespace Microsoft.AspNetCore.Components.Forms [Microsoft.AspNetCore.Components.ParameterAttribute] public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } - protected override string? FormatValueAsString(TValue value) { throw null; } + protected override string? FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; } protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; } } + public partial class InputRadioGroup : Microsoft.AspNetCore.Components.Forms.InputBase + { + public InputRadioGroup() { } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.RenderFragment? ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } + protected override void OnParametersSet() { } + protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; } + } + public partial class InputRadio : Microsoft.AspNetCore.Components.ComponentBase + { + public InputRadio() { } + [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] + public System.Collections.Generic.IReadOnlyDictionary? AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] + public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } + protected override void OnParametersSet() { } + } public partial class InputSelect : Microsoft.AspNetCore.Components.Forms.InputBase { public InputSelect() { } diff --git a/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs b/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs index 7f99fb8ad4..e224abdafc 100644 --- a/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs +++ b/src/Components/Web/ref/Microsoft.AspNetCore.Components.Web.netstandard2.0.cs @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Components.Forms protected TValue CurrentValue { get { throw null; } set { } } protected string? CurrentValueAsString { get { throw null; } set { } } protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - protected Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + protected internal Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } [Microsoft.AspNetCore.Components.ParameterAttribute] public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } [Microsoft.AspNetCore.Components.ParameterAttribute] @@ -96,6 +96,29 @@ namespace Microsoft.AspNetCore.Components.Forms protected override string? FormatValueAsString(TValue value) { throw null; } protected override bool TryParseValueFromString(string? value, out TValue result, out string? validationErrorMessage) { throw null; } } + public partial class InputRadioGroup : Microsoft.AspNetCore.Components.Forms.InputBase + { + public InputRadioGroup() { } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.RenderFragment? ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } + protected override void OnParametersSet() { } + protected override bool TryParseValueFromString(string? value, out TValue result, out string? validationErrorMessage) { throw null; } + } + public partial class InputRadio : Microsoft.AspNetCore.Components.ComponentBase + { + public InputRadio() { } + [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] + public System.Collections.Generic.IReadOnlyDictionary? AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } + protected override void OnParametersSet() { } + } public partial class InputSelect : Microsoft.AspNetCore.Components.Forms.InputBase { public InputSelect() { } diff --git a/src/Components/Web/src/Forms/InputBase.cs b/src/Components/Web/src/Forms/InputBase.cs index b414d3874c..5a8fceecf8 100644 --- a/src/Components/Web/src/Forms/InputBase.cs +++ b/src/Components/Web/src/Forms/InputBase.cs @@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// Gets the for the bound value. /// - protected FieldIdentifier FieldIdentifier { get; set; } + protected internal FieldIdentifier FieldIdentifier { get; set; } /// /// Gets or sets the current value of the input. @@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// The value to format. /// A string representation of the value. - protected virtual string? FormatValueAsString(TValue value) + protected virtual string? FormatValueAsString([AllowNull] TValue value) => value?.ToString(); /// diff --git a/src/Components/Web/src/Forms/InputDate.cs b/src/Components/Web/src/Forms/InputDate.cs index 45583a849e..e7132988b9 100644 --- a/src/Components/Web/src/Forms/InputDate.cs +++ b/src/Components/Web/src/Forms/InputDate.cs @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Components.Forms } /// - protected override string FormatValueAsString(TValue value) + protected override string FormatValueAsString([AllowNull] TValue value) { switch (value) { diff --git a/src/Components/Web/src/Forms/InputExtensions.cs b/src/Components/Web/src/Forms/InputExtensions.cs new file mode 100644 index 0000000000..a1ace92141 --- /dev/null +++ b/src/Components/Web/src/Forms/InputExtensions.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 System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; + +namespace Microsoft.AspNetCore.Components.Forms +{ + internal static class InputExtensions + { + public static bool TryParseSelectableValueFromString(this InputBase input, string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage) + { + try + { + if (BindConverter.TryConvertTo(value, CultureInfo.CurrentCulture, out var parsedValue)) + { + result = parsedValue; + validationErrorMessage = null; + return true; + } + else + { + result = default; + validationErrorMessage = $"The {input.FieldIdentifier.FieldName} field is not valid."; + return false; + } + } + catch (InvalidOperationException ex) + { + throw new InvalidOperationException($"{input.GetType()} does not support the type '{typeof(TValue)}'.", ex); + } + } + } +} diff --git a/src/Components/Web/src/Forms/InputNumber.cs b/src/Components/Web/src/Forms/InputNumber.cs index 9f3b75175e..515fc5ceac 100644 --- a/src/Components/Web/src/Forms/InputNumber.cs +++ b/src/Components/Web/src/Forms/InputNumber.cs @@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Components.Forms /// /// The value to format. /// A string representation of the value. - protected override string? FormatValueAsString(TValue value) + protected override string? FormatValueAsString([AllowNull] TValue value) { // Avoiding a cast to IFormattable to avoid boxing. switch (value) diff --git a/src/Components/Web/src/Forms/InputRadio.cs b/src/Components/Web/src/Forms/InputRadio.cs new file mode 100644 index 0000000000..4a4ad46dc3 --- /dev/null +++ b/src/Components/Web/src/Forms/InputRadio.cs @@ -0,0 +1,82 @@ +// 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.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Components.Rendering; + +namespace Microsoft.AspNetCore.Components.Forms +{ + /// + /// An input component used for selecting a value from a group of choices. + /// + public class InputRadio : ComponentBase + { + /// + /// Gets context for this . + /// + internal InputRadioContext? Context { get; private set; } + + /// + /// Gets or sets a collection of additional attributes that will be applied to the input element. + /// + [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary? AdditionalAttributes { get; set; } + + /// + /// Gets or sets the value of this input. + /// + [AllowNull] + [MaybeNull] + [Parameter] + public TValue Value { get; set; } = default; + + /// + /// Gets or sets the name of the parent input radio group. + /// + [Parameter] public string? Name { get; set; } + + [CascadingParameter] private InputRadioContext? CascadedContext { get; set; } + + private string GetCssClass(string fieldClass) + { + if (AdditionalAttributes != null && + AdditionalAttributes.TryGetValue("class", out var @class) && + !string.IsNullOrEmpty(Convert.ToString(@class))) + { + return $"{@class} {fieldClass}"; + } + + return fieldClass; + } + + /// + protected override void OnParametersSet() + { + Context = string.IsNullOrEmpty(Name) ? CascadedContext : CascadedContext?.FindContextInAncestors(Name); + + if (Context == null) + { + throw new InvalidOperationException($"{GetType()} must have an ancestor {typeof(InputRadioGroup)} " + + $"with a matching 'Name' property, if specified."); + } + } + + /// + protected override void BuildRenderTree(RenderTreeBuilder builder) + { + Debug.Assert(Context != null); + + builder.OpenElement(0, "input"); + builder.AddMultipleAttributes(1, AdditionalAttributes); + builder.AddAttribute(2, "class", GetCssClass(Context.FieldClass)); + builder.AddAttribute(3, "type", "radio"); + builder.AddAttribute(4, "name", Context.GroupName); + builder.AddAttribute(5, "value", BindConverter.FormatValue(Value?.ToString())); + builder.AddAttribute(6, "checked", Context.CurrentValue?.Equals(Value)); + builder.AddAttribute(7, "onchange", Context.ChangeEventCallback); + builder.CloseElement(); + } + } +} diff --git a/src/Components/Web/src/Forms/InputRadioContext.cs b/src/Components/Web/src/Forms/InputRadioContext.cs new file mode 100644 index 0000000000..45f302871b --- /dev/null +++ b/src/Components/Web/src/Forms/InputRadioContext.cs @@ -0,0 +1,64 @@ +// 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.Components.Forms +{ + /// + /// Describes context for an component. + /// + internal class InputRadioContext + { + private readonly InputRadioContext? _parentContext; + + /// + /// Gets the name of the input radio group. + /// + public string GroupName { get; } + + /// + /// Gets the current selected value in the input radio group. + /// + public object? CurrentValue { get; } + + /// + /// Gets a css class indicating the validation state of input radio elements. + /// + public string FieldClass { get; } + + /// + /// Gets the event callback to be invoked when the selected value is changed. + /// + public EventCallback ChangeEventCallback { get; } + + /// + /// Instantiates a new . + /// + /// The parent . + /// The name of the input radio group. + /// The current selected value in the input radio group. + /// The css class indicating the validation state of input radio elements. + /// The event callback to be invoked when the selected value is changed. + public InputRadioContext( + InputRadioContext? parentContext, + string groupName, + object? currentValue, + string fieldClass, + EventCallback changeEventCallback) + { + _parentContext = parentContext; + + GroupName = groupName; + CurrentValue = currentValue; + FieldClass = fieldClass; + ChangeEventCallback = changeEventCallback; + } + + /// + /// Finds an in the context's ancestors with the matching . + /// + /// The group name of the ancestor . + /// The , or null if none was found. + public InputRadioContext? FindContextInAncestors(string groupName) + => string.Equals(GroupName, groupName) ? this : _parentContext?.FindContextInAncestors(groupName); + } +} diff --git a/src/Components/Web/src/Forms/InputRadioGroup.cs b/src/Components/Web/src/Forms/InputRadioGroup.cs new file mode 100644 index 0000000000..0e30fd483e --- /dev/null +++ b/src/Components/Web/src/Forms/InputRadioGroup.cs @@ -0,0 +1,57 @@ +// 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.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Components.Rendering; + +namespace Microsoft.AspNetCore.Components.Forms +{ + /// + /// Groups child components. + /// + public class InputRadioGroup : InputBase + { + private readonly string _defaultGroupName = Guid.NewGuid().ToString("N"); + private InputRadioContext? _context; + + /// + /// Gets or sets the child content to be rendering inside the . + /// + [Parameter] public RenderFragment? ChildContent { get; set; } + + /// + /// Gets or sets the name of the group. + /// + [Parameter] public string? Name { get; set; } + + [CascadingParameter] private InputRadioContext? CascadedContext { get; set; } + + /// + protected override void OnParametersSet() + { + var groupName = !string.IsNullOrEmpty(Name) ? Name : _defaultGroupName; + var fieldClass = EditContext.FieldCssClass(FieldIdentifier); + var changeEventCallback = EventCallback.Factory.CreateBinder(this, __value => CurrentValueAsString = __value, CurrentValueAsString); + + _context = new InputRadioContext(CascadedContext, groupName, CurrentValue, fieldClass, changeEventCallback); + } + + /// + protected override void BuildRenderTree(RenderTreeBuilder builder) + { + Debug.Assert(_context != null); + + builder.OpenComponent>(2); + builder.AddAttribute(3, "IsFixed", true); + builder.AddAttribute(4, "Value", _context); + builder.AddAttribute(5, "ChildContent", ChildContent); + builder.CloseComponent(); + } + + /// + protected override bool TryParseValueFromString(string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage) + => this.TryParseSelectableValueFromString(value, out result, out validationErrorMessage); + } +} diff --git a/src/Components/Web/src/Forms/InputSelect.cs b/src/Components/Web/src/Forms/InputSelect.cs index c5e6e54a94..b7d5dd7025 100644 --- a/src/Components/Web/src/Forms/InputSelect.cs +++ b/src/Components/Web/src/Forms/InputSelect.cs @@ -1,9 +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; using System.Diagnostics.CodeAnalysis; -using System.Globalization; using Microsoft.AspNetCore.Components.Rendering; namespace Microsoft.AspNetCore.Components.Forms @@ -13,8 +11,6 @@ namespace Microsoft.AspNetCore.Components.Forms /// public class InputSelect : InputBase { - private static readonly Type? _nullableUnderlyingType = Nullable.GetUnderlyingType(typeof(TValue)); - /// /// Gets or sets the child content to be rendering inside the select element. /// @@ -34,31 +30,6 @@ namespace Microsoft.AspNetCore.Components.Forms /// protected override bool TryParseValueFromString(string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage) - { - if (typeof(TValue) == typeof(string)) - { - result = (TValue)(object?)value; - validationErrorMessage = null; - return true; - } - else if (typeof(TValue).IsEnum || (_nullableUnderlyingType != null && _nullableUnderlyingType.IsEnum)) - { - var success = BindConverter.TryConvertTo(value, CultureInfo.CurrentCulture, out var parsedValue); - if (success) - { - result = parsedValue; - validationErrorMessage = null; - return true; - } - else - { - result = default; - validationErrorMessage = $"The {FieldIdentifier.FieldName} field is not valid."; - return false; - } - } - - throw new InvalidOperationException($"{GetType()} does not support the type '{typeof(TValue)}'."); - } + => this.TryParseSelectableValueFromString(value, out result, out validationErrorMessage); } } diff --git a/src/Components/Web/src/Properties/AssemblyInfo.cs b/src/Components/Web/src/Properties/AssemblyInfo.cs index 2741560028..891ea5326c 100644 --- a/src/Components/Web/src/Properties/AssemblyInfo.cs +++ b/src/Components/Web/src/Properties/AssemblyInfo.cs @@ -1,3 +1,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Server.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Web.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Components/Web/test/Forms/InputRadioTest.cs b/src/Components/Web/test/Forms/InputRadioTest.cs new file mode 100644 index 0000000000..1447a16316 --- /dev/null +++ b/src/Components/Web/test/Forms/InputRadioTest.cs @@ -0,0 +1,138 @@ +// 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.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.Rendering; +using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Test.Helpers; +using Xunit; + +namespace Microsoft.AspNetCore.Components.Forms +{ + public class InputRadioTest + { + [Fact] + public async Task ThrowsOnFirstRenderIfInputRadioHasNoGroup() + { + var model = new TestModel(); + var rootComponent = new TestInputRadioHostComponent + { + EditContext = new EditContext(model), + InnerContent = RadioButtonsWithoutGroup(null) + }; + + var ex = await Assert.ThrowsAsync(() => RenderAndGetTestInputComponentAsync(rootComponent)); + Assert.Contains($"must have an ancestor", ex.Message); + } + + [Fact] + public async Task GroupGeneratesNameGuidWhenInvalidNameSupplied() + { + var model = new TestModel(); + var rootComponent = new TestInputRadioHostComponent + { + EditContext = new EditContext(model), + InnerContent = RadioButtonsWithGroup(null, () => model.TestEnum) + }; + + var inputRadioComponents = await RenderAndGetTestInputComponentAsync(rootComponent); + + Assert.All(inputRadioComponents, inputRadio => Assert.True(Guid.TryParseExact(inputRadio.GroupName, "N", out _))); + } + + [Fact] + public async Task RadioInputContextExistsWhenValidNameSupplied() + { + var groupName = "group"; + var model = new TestModel(); + var rootComponent = new TestInputRadioHostComponent + { + EditContext = new EditContext(model), + InnerContent = RadioButtonsWithGroup(groupName, () => model.TestEnum) + }; + + var inputRadioComponents = await RenderAndGetTestInputComponentAsync(rootComponent); + + Assert.All(inputRadioComponents, inputRadio => Assert.Equal(groupName, inputRadio.GroupName)); + } + + private static RenderFragment RadioButtonsWithoutGroup(string name) => (builder) => + { + foreach (var selectedValue in (TestEnum[])Enum.GetValues(typeof(TestEnum))) + { + builder.OpenComponent(0); + builder.AddAttribute(1, "Name", name); + builder.AddAttribute(2, "Value", selectedValue); + builder.CloseComponent(); + } + }; + + private static RenderFragment RadioButtonsWithGroup(string name, Expression> valueExpression) => (builder) => + { + builder.OpenComponent>(0); + builder.AddAttribute(1, "Name", name); + builder.AddAttribute(2, "ValueExpression", valueExpression); + builder.AddAttribute(2, "ChildContent", new RenderFragment((childBuilder) => + { + foreach (var value in (TestEnum[])Enum.GetValues(typeof(TestEnum))) + { + childBuilder.OpenComponent(0); + childBuilder.AddAttribute(1, "Value", value); + childBuilder.CloseComponent(); + } + })); + + builder.CloseComponent(); + }; + + private static IEnumerable FindInputRadioComponents(CapturedBatch batch) + => batch.ReferenceFrames + .Where(f => f.FrameType == RenderTreeFrameType.Component) + .Select(f => f.Component) + .OfType(); + + private static async Task> RenderAndGetTestInputComponentAsync(TestInputRadioHostComponent rootComponent) + { + var testRenderer = new TestRenderer(); + var componentId = testRenderer.AssignRootComponentId(rootComponent); + await testRenderer.RenderRootComponentAsync(componentId); + return FindInputRadioComponents(testRenderer.Batches.Single()); + } + + private enum TestEnum + { + One, + Two, + Three + } + + private class TestModel + { + public TestEnum TestEnum { get; set; } + } + + private class TestInputRadio : InputRadio + { + public string GroupName => Context.GroupName; + } + + private class TestInputRadioHostComponent : AutoRenderComponent + { + public EditContext EditContext { get; set; } + + public RenderFragment InnerContent { get; set; } + + protected override void BuildRenderTree(RenderTreeBuilder builder) + { + builder.OpenComponent>(0); + builder.AddAttribute(1, "Value", EditContext); + builder.AddAttribute(2, "ChildContent", InnerContent); + builder.CloseComponent(); + } + } + } +} diff --git a/src/Components/Web/test/Forms/InputSelectTest.cs b/src/Components/Web/test/Forms/InputSelectTest.cs index 7c49fe03be..65c3351e5e 100644 --- a/src/Components/Web/test/Forms/InputSelectTest.cs +++ b/src/Components/Web/test/Forms/InputSelectTest.cs @@ -90,6 +90,88 @@ namespace Microsoft.AspNetCore.Components.Forms Assert.Null(inputSelectComponent.CurrentValue); } + // See: https://github.com/dotnet/aspnetcore/issues/9939 + [Fact] + public async Task ParsesCurrentValueWhenUsingNotNullableGuid() + { + // Arrange + var model = new TestModel(); + var rootComponent = new TestInputSelectHostComponent + { + EditContext = new EditContext(model), + ValueExpression = () => model.NotNullableGuid + }; + var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); + + // Act + var guid = Guid.NewGuid(); + inputSelectComponent.CurrentValueAsString = guid.ToString(); + + // Assert + Assert.Equal(guid, inputSelectComponent.CurrentValue); + } + + // See: https://github.com/dotnet/aspnetcore/issues/9939 + [Fact] + public async Task ParsesCurrentValueWhenUsingNullableGuid() + { + // Arrange + var model = new TestModel(); + var rootComponent = new TestInputSelectHostComponent + { + EditContext = new EditContext(model), + ValueExpression = () => model.NullableGuid + }; + var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); + + // Act + var guid = Guid.NewGuid(); + inputSelectComponent.CurrentValueAsString = guid.ToString(); + + // Assert + Assert.Equal(guid, inputSelectComponent.CurrentValue); + } + + // See: https://github.com/dotnet/aspnetcore/pull/19562 + [Fact] + public async Task ParsesCurrentValueWhenUsingNotNullableInt() + { + // Arrange + var model = new TestModel(); + var rootComponent = new TestInputSelectHostComponent + { + EditContext = new EditContext(model), + ValueExpression = () => model.NotNullableInt + }; + var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); + + // Act + inputSelectComponent.CurrentValueAsString = "42"; + + // Assert + Assert.Equal(42, inputSelectComponent.CurrentValue); + } + + // See: https://github.com/dotnet/aspnetcore/pull/19562 + [Fact] + public async Task ParsesCurrentValueWhenUsingNullableInt() + { + // Arrange + var model = new TestModel(); + var rootComponent = new TestInputSelectHostComponent + { + EditContext = new EditContext(model), + ValueExpression = () => model.NullableInt + }; + var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); + + // Act + inputSelectComponent.CurrentValueAsString = "42"; + + // Assert + Assert.Equal(42, inputSelectComponent.CurrentValue); + } + private static TestInputSelect FindInputSelectComponent(CapturedBatch batch) => batch.ReferenceFrames .Where(f => f.FrameType == RenderTreeFrameType.Component) @@ -117,6 +199,14 @@ namespace Microsoft.AspNetCore.Components.Forms public TestEnum NotNullableEnum { get; set; } public TestEnum? NullableEnum { get; set; } + + public Guid NotNullableGuid { get; set; } + + public Guid? NullableGuid { get; set; } + + public int NotNullableInt { get; set; } + + public int? NullableInt { get; set; } } class TestInputSelect : InputSelect diff --git a/src/Components/test/E2ETest/Tests/FormsTest.cs b/src/Components/test/E2ETest/Tests/FormsTest.cs index 90d298502d..15495dc7da 100644 --- a/src/Components/test/E2ETest/Tests/FormsTest.cs +++ b/src/Components/test/E2ETest/Tests/FormsTest.cs @@ -301,6 +301,68 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests Browser.Equal(new[] { "Must accept terms", "Must not be evil" }, messagesAccessor); } + [Fact] + public void InputRadioGroupWithoutNameInteractsWithEditContext() + { + var appElement = MountTypicalValidationComponent(); + var airlineInputs = appElement.FindElement(By.ClassName("airline")).FindElements(By.TagName("input")); + var unknownAirlineInput = airlineInputs.First(i => i.GetAttribute("value").Equals("Unknown")); + var bestAirlineInput = airlineInputs.First(i => i.GetAttribute("value").Equals("BestAirline")); + var messagesAccessor = CreateValidationMessagesAccessor(appElement); + + // Validate unselected inputs + Assert.All(airlineInputs.Where(i => i != unknownAirlineInput), i => Browser.False(() => i.Selected)); + + // Validate selected inputs + Browser.True(() => unknownAirlineInput.Selected); + + // InputRadio emits additional attributes + Browser.True(() => unknownAirlineInput.GetAttribute("extra").Equals("additional")); + + // Validates on edit + Assert.All(airlineInputs, i => Browser.Equal("valid", () => i.GetAttribute("class"))); + bestAirlineInput.Click(); + Assert.All(airlineInputs, i => Browser.Equal("modified valid", () => i.GetAttribute("class"))); + + // Can become invalid + unknownAirlineInput.Click(); + Assert.All(airlineInputs, i => Browser.Equal("modified invalid", () => i.GetAttribute("class"))); + Browser.Equal(new[] { "Pick a valid airline." }, messagesAccessor); + } + + [Fact] + public void InputRadioGroupsWithNamesNestedInteractWithEditContext() + { + var appElement = MountTypicalValidationComponent(); + var submitButton = appElement.FindElement(By.CssSelector("button[type=submit]")); + var group = appElement.FindElement(By.ClassName("nested-radio-group")); + var countryInputs = group.FindElements(By.Name("country")); + var colorInputs = group.FindElements(By.Name("color")); + + // Validate group counts + Assert.Equal(3, countryInputs.Count); + Assert.Equal(4, colorInputs.Count); + + // Validate unselected inputs + Assert.All(countryInputs, i => Browser.False(() => i.Selected)); + Assert.All(colorInputs, i => Browser.False(() => i.Selected)); + + // Invalidates on submit + Assert.All(countryInputs, i => Browser.Equal("valid", () => i.GetAttribute("class"))); + Assert.All(colorInputs, i => Browser.Equal("valid", () => i.GetAttribute("class"))); + submitButton.Click(); + Assert.All(countryInputs, i => Browser.Equal("invalid", () => i.GetAttribute("class"))); + Assert.All(colorInputs, i => Browser.Equal("invalid", () => i.GetAttribute("class"))); + + // Validates on edit + countryInputs.First().Click(); + Assert.All(countryInputs, i => Browser.Equal("modified valid", () => i.GetAttribute("class"))); + Assert.All(colorInputs, i => Browser.Equal("invalid", () => i.GetAttribute("class"))); + + colorInputs.First().Click(); + Assert.All(colorInputs, i => Browser.Equal("modified valid", () => i.GetAttribute("class"))); + } + [Fact] public void CanWireUpINotifyPropertyChangedToEditContext() { diff --git a/src/Components/test/testassets/BasicTestApp/FormsTest/TypicalValidationComponent.razor b/src/Components/test/testassets/BasicTestApp/FormsTest/TypicalValidationComponent.razor index 69c2f58501..4cf0a9d80f 100644 --- a/src/Components/test/testassets/BasicTestApp/FormsTest/TypicalValidationComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/FormsTest/TypicalValidationComponent.razor @@ -40,6 +40,32 @@ @person.TicketClass

+

+ + Airline: +
+ @foreach (var airline in (Airline[])Enum.GetValues(typeof(Airline))) + { + + @airline.ToString(); +
+ } +
+

+

+ Pick one color and one country: + + + red
+ japan
+ green
+ yemen
+ blue
+ latvia
+ orange
+
+
+

Accepts terms:

@@ -109,11 +135,27 @@ [Required, EnumDataType(typeof(TicketClass))] public TicketClass TicketClass { get; set; } + [Required] + [Range(typeof(Airline), nameof(Airline.BestAirline), nameof(Airline.NoNameAirline), ErrorMessage = "Pick a valid airline.")] + public Airline Airline { get; set; } = Airline.Unknown; + + [Required, EnumDataType(typeof(Color))] + public Color? FavoriteColor { get; set; } = null; + + [Required, EnumDataType(typeof(Country))] + public Country? Country { get; set; } = null; + public string Username { get; set; } } enum TicketClass { Economy, Premium, First } + enum Airline { BestAirline, CoolAirline, NoNameAirline, Unknown } + + enum Color { Red, Green, Blue, Orange } + + enum Country { Japan, Yemen, Latvia } + List submissionLog = new List(); // So we can assert about the callbacks void HandleValidSubmit() From aedcfbd5c0350ad7dd1e882cafbaf692b979b2e8 Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 2 Jul 2020 13:23:40 -0700 Subject: [PATCH 087/100] Update RequestTests.cs (#23629) --- .../Kestrel/test/InMemory.FunctionalTests/RequestTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs index 088d8f0242..f20418b9d1 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs @@ -1048,6 +1048,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23628")] public async Task ContentLengthReadAsyncSingleBytesAtATime() { var testContext = new TestServiceContext(LoggerFactory); From 36856ca8f9932b88757bbf24904bf36868b4d727 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 2 Jul 2020 14:29:04 -0700 Subject: [PATCH 088/100] Revive support for component governance variable (#23624) --- .azure/pipelines/jobs/default-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/pipelines/jobs/default-build.yml b/.azure/pipelines/jobs/default-build.yml index f851f512f2..e13f4bfb55 100644 --- a/.azure/pipelines/jobs/default-build.yml +++ b/.azure/pipelines/jobs/default-build.yml @@ -242,7 +242,7 @@ jobs: continueOnError: true condition: always() - - ${{ if and(startsWith(parameters.jobDisplayName, 'Build:'), ne(parameters.skipComponentGovernanceDetection, 'true'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if and(startsWith(parameters.jobDisplayName, 'Build:'), ne(variables['skipComponentGovernanceDetection'], 'true'), ne(parameters.skipComponentGovernanceDetection, 'true'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 condition: and(succeeded(), ne(variables['CG_RAN'], 'true')) displayName: 'Component Detection' From c67ecd2cf0e4aa9f6b81903fdadd9ec3e495f5ad Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 2 Jul 2020 15:26:28 -0700 Subject: [PATCH 089/100] Quarantine test --- .../BlazorTemplates.Tests/BlazorWasmTemplateTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs index a63c8c4dfd..decd986856 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs @@ -330,6 +330,7 @@ namespace Templates.Test } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23639")] public async Task BlazorWasmStandaloneTemplate_IndividualAuth_Works() { var project = await ProjectFactory.GetOrCreateProject("blazorstandaloneindividual", Output); From 8182bb16a9e2baf3d656b2212dd458689c313b99 Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Thu, 2 Jul 2020 16:20:55 -0700 Subject: [PATCH 090/100] Disable cookie name encoding/decoding. (#23579) --- .../src/Internal/RequestCookieCollection.cs | 5 +- src/Http/Http/src/Internal/ResponseCookies.cs | 9 ++-- .../test/Internal/DefaultHttpRequestTests.cs | 4 +- .../test/RequestCookiesCollectionTests.cs | 42 +++++++-------- src/Http/Http/test/ResponseCookiesTest.cs | 54 ++++++++++++------- 5 files changed, 67 insertions(+), 47 deletions(-) diff --git a/src/Http/Http/src/Internal/RequestCookieCollection.cs b/src/Http/Http/src/Internal/RequestCookieCollection.cs index 6c74a6769b..d6542a23d7 100644 --- a/src/Http/Http/src/Internal/RequestCookieCollection.cs +++ b/src/Http/Http/src/Internal/RequestCookieCollection.cs @@ -57,6 +57,9 @@ namespace Microsoft.AspNetCore.Http } public static RequestCookieCollection Parse(IList values) + => ParseInternal(values, AppContext.TryGetSwitch(ResponseCookies.EnableCookieNameEncoding, out var enabled) && enabled); + + internal static RequestCookieCollection ParseInternal(IList values, bool enableCookieNameEncoding) { if (values.Count == 0) { @@ -75,7 +78,7 @@ namespace Microsoft.AspNetCore.Http for (var i = 0; i < cookies.Count; i++) { var cookie = cookies[i]; - var name = Uri.UnescapeDataString(cookie.Name.Value); + var name = enableCookieNameEncoding ? Uri.UnescapeDataString(cookie.Name.Value) : cookie.Name.Value; var value = Uri.UnescapeDataString(cookie.Value.Value); store[name] = value; } diff --git a/src/Http/Http/src/Internal/ResponseCookies.cs b/src/Http/Http/src/Internal/ResponseCookies.cs index 1de354e342..d9adfb69f1 100644 --- a/src/Http/Http/src/Internal/ResponseCookies.cs +++ b/src/Http/Http/src/Internal/ResponseCookies.cs @@ -13,6 +13,9 @@ namespace Microsoft.AspNetCore.Http ///
internal class ResponseCookies : IResponseCookies { + internal const string EnableCookieNameEncoding = "Microsoft.AspNetCore.Http.EnableCookieNameEncoding"; + internal bool _enableCookieNameEncoding = AppContext.TryGetSwitch(EnableCookieNameEncoding, out var enabled) && enabled; + /// /// Create a new wrapper. /// @@ -33,7 +36,7 @@ namespace Microsoft.AspNetCore.Http public void Append(string key, string value) { var setCookieHeaderValue = new SetCookieHeaderValue( - Uri.EscapeDataString(key), + _enableCookieNameEncoding ? Uri.EscapeDataString(key) : key, Uri.EscapeDataString(value)) { Path = "/" @@ -52,7 +55,7 @@ namespace Microsoft.AspNetCore.Http } var setCookieHeaderValue = new SetCookieHeaderValue( - Uri.EscapeDataString(key), + _enableCookieNameEncoding ? Uri.EscapeDataString(key) : key, Uri.EscapeDataString(value)) { Domain = options.Domain, @@ -83,7 +86,7 @@ namespace Microsoft.AspNetCore.Http throw new ArgumentNullException(nameof(options)); } - var encodedKeyPlusEquals = Uri.EscapeDataString(key) + "="; + var encodedKeyPlusEquals = (_enableCookieNameEncoding ? Uri.EscapeDataString(key) : key) + "="; bool domainHasValue = !string.IsNullOrEmpty(options.Domain); bool pathHasValue = !string.IsNullOrEmpty(options.Path); diff --git a/src/Http/Http/test/Internal/DefaultHttpRequestTests.cs b/src/Http/Http/test/Internal/DefaultHttpRequestTests.cs index da9a846277..ddd17f143d 100644 --- a/src/Http/Http/test/Internal/DefaultHttpRequestTests.cs +++ b/src/Http/Http/test/Internal/DefaultHttpRequestTests.cs @@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.Http Assert.Null(cookies0["key0"]); Assert.False(cookies0.ContainsKey("key0")); - var newCookies = new[] { "name0=value0%2C", "%5Ename1=value1" }; + var newCookies = new[] { "name0=value0%2C", "name1=value1" }; request.Headers["Cookie"] = newCookies; cookies0 = RequestCookieCollection.Parse(newCookies); @@ -183,7 +183,7 @@ namespace Microsoft.AspNetCore.Http Assert.Equal(cookies0, cookies1); Assert.Equal(2, cookies1.Count); Assert.Equal("value0,", cookies1["name0"]); - Assert.Equal("value1", cookies1["^name1"]); + Assert.Equal("value1", cookies1["name1"]); Assert.Equal(newCookies, request.Headers["Cookie"]); var cookies2 = new RequestCookieCollection(new Dictionary() diff --git a/src/Http/Http/test/RequestCookiesCollectionTests.cs b/src/Http/Http/test/RequestCookiesCollectionTests.cs index 0d3cf069ad..8d3dad77f6 100644 --- a/src/Http/Http/test/RequestCookiesCollectionTests.cs +++ b/src/Http/Http/test/RequestCookiesCollectionTests.cs @@ -9,28 +9,13 @@ namespace Microsoft.AspNetCore.Http.Tests { public class RequestCookiesCollectionTests { - public static TheoryData UnEscapesKeyValues_Data - { - get - { - // key, value, expected - return new TheoryData - { - { "key=value", "key", "value" }, - { "key%2C=%21value", "key,", "!value" }, - { "ke%23y%2C=val%5Eue", "ke#y,", "val^ue" }, - { "base64=QUI%2BREU%2FRw%3D%3D", "base64", "QUI+REU/Rw==" }, - { "base64=QUI+REU/Rw==", "base64", "QUI+REU/Rw==" }, - }; - } - } - [Theory] - [MemberData(nameof(UnEscapesKeyValues_Data))] - public void UnEscapesKeyValues( - string input, - string expectedKey, - string expectedValue) + [InlineData("key=value", "key", "value")] + [InlineData("key%2C=%21value", "key%2C", "!value")] + [InlineData("ke%23y%2C=val%5Eue", "ke%23y%2C", "val^ue")] + [InlineData("base64=QUI%2BREU%2FRw%3D%3D", "base64", "QUI+REU/Rw==")] + [InlineData("base64=QUI+REU/Rw==", "base64", "QUI+REU/Rw==")] + public void UnEscapesValues(string input, string expectedKey, string expectedValue) { var cookies = RequestCookieCollection.Parse(new StringValues(input)); @@ -38,5 +23,20 @@ namespace Microsoft.AspNetCore.Http.Tests Assert.Equal(expectedKey, cookies.Keys.Single()); Assert.Equal(expectedValue, cookies[expectedKey]); } + + [Theory] + [InlineData("key=value", "key", "value")] + [InlineData("key%2C=%21value", "key,", "!value")] + [InlineData("ke%23y%2C=val%5Eue", "ke#y,", "val^ue")] + [InlineData("base64=QUI%2BREU%2FRw%3D%3D", "base64", "QUI+REU/Rw==")] + [InlineData("base64=QUI+REU/Rw==", "base64", "QUI+REU/Rw==")] + public void AppContextSwitchUnEscapesKeysAndValues(string input, string expectedKey, string expectedValue) + { + var cookies = RequestCookieCollection.ParseInternal(new StringValues(input), enableCookieNameEncoding: true); + + Assert.Equal(1, cookies.Count); + Assert.Equal(expectedKey, cookies.Keys.Single()); + Assert.Equal(expectedValue, cookies[expectedKey]); + } } } diff --git a/src/Http/Http/test/ResponseCookiesTest.cs b/src/Http/Http/test/ResponseCookiesTest.cs index 23eea058de..8e4e60aaa9 100644 --- a/src/Http/Http/test/ResponseCookiesTest.cs +++ b/src/Http/Http/test/ResponseCookiesTest.cs @@ -88,31 +88,45 @@ namespace Microsoft.AspNetCore.Http.Tests Assert.Contains($"max-age={maxAgeTime.TotalSeconds.ToString()}", cookieHeaderValues[0]); } - public static TheoryData EscapesKeyValuesBeforeSettingCookieData - { - get - { - // key, value, object pool, expected - return new TheoryData - { - { "key", "value", "key=value" }, - { "key,", "!value", "key%2C=%21value" }, - { "ke#y,", "val^ue", "ke%23y%2C=val%5Eue" }, - { "base64", "QUI+REU/Rw==", "base64=QUI%2BREU%2FRw%3D%3D" }, - }; - } - } - [Theory] - [MemberData(nameof(EscapesKeyValuesBeforeSettingCookieData))] - public void EscapesKeyValuesBeforeSettingCookie( - string key, - string value, - string expected) + [InlineData("value", "key=value")] + [InlineData("!value", "key=%21value")] + [InlineData("val^ue", "key=val%5Eue")] + [InlineData("QUI+REU/Rw==", "key=QUI%2BREU%2FRw%3D%3D")] + public void EscapesValuesBeforeSettingCookie(string value, string expected) { var headers = new HeaderDictionary(); var cookies = new ResponseCookies(headers); + cookies.Append("key", value); + + var cookieHeaderValues = headers[HeaderNames.SetCookie]; + Assert.Single(cookieHeaderValues); + Assert.StartsWith(expected, cookieHeaderValues[0]); + } + + [Theory] + [InlineData("key,")] + [InlineData("ke@y")] + public void InvalidKeysThrow(string key) + { + var headers = new HeaderDictionary(); + var cookies = new ResponseCookies(headers); + + Assert.Throws(() => cookies.Append(key, "1")); + } + + [Theory] + [InlineData("key", "value", "key=value")] + [InlineData("key,", "!value", "key%2C=%21value")] + [InlineData("ke#y,", "val^ue", "ke%23y%2C=val%5Eue")] + [InlineData("base64", "QUI+REU/Rw==", "base64=QUI%2BREU%2FRw%3D%3D")] + public void AppContextSwitchEscapesKeysAndValuesBeforeSettingCookie(string key, string value, string expected) + { + var headers = new HeaderDictionary(); + var cookies = new ResponseCookies(headers); + cookies._enableCookieNameEncoding = true; + cookies.Append(key, value); var cookieHeaderValues = headers[HeaderNames.SetCookie]; From 83448b47a0960aeb87169192f20888884796a243 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 3 Jul 2020 05:03:23 +0000 Subject: [PATCH 091/100] Update dependencies from https://github.com/dotnet/efcore build 20200702.2 (#23650) Microsoft.EntityFrameworkCore.Tools , Microsoft.EntityFrameworkCore.SqlServer , dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.InMemory From Version 5.0.0-preview.8.20351.2 -> To Version 5.0.0-preview.8.20352.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ec2d412702..ef86d45efb 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,33 +13,33 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 + 297130c06b1de9c32749d63490c010db37c2ce43 - + https://github.com/dotnet/efcore - e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 + 297130c06b1de9c32749d63490c010db37c2ce43 - + https://github.com/dotnet/efcore - e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 + 297130c06b1de9c32749d63490c010db37c2ce43 - + https://github.com/dotnet/efcore - e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 + 297130c06b1de9c32749d63490c010db37c2ce43 - + https://github.com/dotnet/efcore - e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 + 297130c06b1de9c32749d63490c010db37c2ce43 - + https://github.com/dotnet/efcore - e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 + 297130c06b1de9c32749d63490c010db37c2ce43 - + https://github.com/dotnet/efcore - e327d2cb82b868f9a8eb7c0d1fa7bcc77e69a1b4 + 297130c06b1de9c32749d63490c010db37c2ce43 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 555ae79bc1..af4a655854 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -132,13 +132,13 @@ 3.2.0 - 5.0.0-preview.8.20351.2 - 5.0.0-preview.8.20351.2 - 5.0.0-preview.8.20351.2 - 5.0.0-preview.8.20351.2 - 5.0.0-preview.8.20351.2 - 5.0.0-preview.8.20351.2 - 5.0.0-preview.8.20351.2 + 5.0.0-preview.8.20352.2 + 5.0.0-preview.8.20352.2 + 5.0.0-preview.8.20352.2 + 5.0.0-preview.8.20352.2 + 5.0.0-preview.8.20352.2 + 5.0.0-preview.8.20352.2 + 5.0.0-preview.8.20352.2 - + https://github.com/dotnet/runtime - 719c58c88dc22fe07bcb64f07ba5a74cc10d274c + d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5 - + https://github.com/dotnet/runtime - 719c58c88dc22fe07bcb64f07ba5a74cc10d274c + d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5 - + https://github.com/dotnet/runtime - 719c58c88dc22fe07bcb64f07ba5a74cc10d274c + d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index af4a655854..34a520b3a3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -66,79 +66,79 @@ 3.7.0-4.20319.6 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 - 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 + 5.0.0-preview.8.20352.6 - 5.0.0-preview.8.20351.9 + 5.0.0-preview.8.20352.6 3.2.0 - 5.0.0-preview.8.20352.2 - 5.0.0-preview.8.20352.2 - 5.0.0-preview.8.20352.2 - 5.0.0-preview.8.20352.2 - 5.0.0-preview.8.20352.2 - 5.0.0-preview.8.20352.2 - 5.0.0-preview.8.20352.2 + 5.0.0-preview.8.20353.1 + 5.0.0-preview.8.20353.1 + 5.0.0-preview.8.20353.1 + 5.0.0-preview.8.20353.1 + 5.0.0-preview.8.20353.1 + 5.0.0-preview.8.20353.1 + 5.0.0-preview.8.20353.1 3.2.0 - 5.0.0-preview.8.20353.1 - 5.0.0-preview.8.20353.1 - 5.0.0-preview.8.20353.1 - 5.0.0-preview.8.20353.1 - 5.0.0-preview.8.20353.1 - 5.0.0-preview.8.20353.1 - 5.0.0-preview.8.20353.1 + 5.0.0-preview.8.20353.3 + 5.0.0-preview.8.20353.3 + 5.0.0-preview.8.20353.3 + 5.0.0-preview.8.20353.3 + 5.0.0-preview.8.20353.3 + 5.0.0-preview.8.20353.3 + 5.0.0-preview.8.20353.3 3.2.0 - 5.0.0-preview.8.20353.3 - 5.0.0-preview.8.20353.3 - 5.0.0-preview.8.20353.3 - 5.0.0-preview.8.20353.3 - 5.0.0-preview.8.20353.3 - 5.0.0-preview.8.20353.3 - 5.0.0-preview.8.20353.3 + 5.0.0-preview.8.20353.4 + 5.0.0-preview.8.20353.4 + 5.0.0-preview.8.20353.4 + 5.0.0-preview.8.20353.4 + 5.0.0-preview.8.20353.4 + 5.0.0-preview.8.20353.4 + 5.0.0-preview.8.20353.4 3.2.0 - 5.0.0-preview.8.20353.4 - 5.0.0-preview.8.20353.4 - 5.0.0-preview.8.20353.4 - 5.0.0-preview.8.20353.4 - 5.0.0-preview.8.20353.4 - 5.0.0-preview.8.20353.4 - 5.0.0-preview.8.20353.4 + 5.0.0-preview.8.20353.5 + 5.0.0-preview.8.20353.5 + 5.0.0-preview.8.20353.5 + 5.0.0-preview.8.20353.5 + 5.0.0-preview.8.20353.5 + 5.0.0-preview.8.20353.5 + 5.0.0-preview.8.20353.5