From f7d2fac8a2d2818e4bfcb36e92b69c465161d2dc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 22 Jun 2020 12:11:55 -0700 Subject: [PATCH 01/38] 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 02/38] 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 03/38] 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 04/38] 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 05/38] [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 10/38] 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 11/38] 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 12/38] [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 13/38] 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 14/38] 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 21/38] 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 22/38] 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 23/38] 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 24/38] 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 25/38] 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 26/38] 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