Przeglądaj źródła

Merge branch 'merge/release/3.1-to-master'

Javier Calvarro Nelson 6 lat temu
rodzic
commit
ea1cb045a6

+ 1 - 1
src/Framework/src/Microsoft.AspNetCore.App.Runtime.csproj

@@ -25,7 +25,7 @@ This package is an internal implementation of the .NET Core SDK and is not meant
     <BaseRuntimeVersionFileName>aspnetcore_base_runtime.version</BaseRuntimeVersionFileName>
     <BaseRuntimeVersionFileOutputPath>$(InstallersOutputPath)$(BaseRuntimeVersionFileName)</BaseRuntimeVersionFileOutputPath>
 
-    <!-- NuGet appends target framework to this value. Example: runtimes/win-x64/lib/netcoreapp5.0/ -->
+    <!-- NuGet appends target framework to this value. Example: runtimes/win-x64/lib/netcoreappX.Y/ -->
     <BuildOutputTargetFolder>runtimes/$(RuntimeIdentifier)/lib/</BuildOutputTargetFolder>
     <!-- We still need the native path to these assets though for the RuntimeList.xml manifest -->
     <ManagedAssetsPackagePath>$(BuildOutputTargetFolder)$(DefaultNetCoreTargetFramework)</ManagedAssetsPackagePath>

+ 2 - 1
src/Mvc/Mvc.Analyzers/src/DiagnosticDescriptors.cs

@@ -47,7 +47,8 @@ namespace Microsoft.AspNetCore.Mvc.Analyzers
             new DiagnosticDescriptor(
                 "MVC1004",
                 "Rename model bound parameter.",
-                "Property on type '{0}' has the same name as parameter '{1}'. This may result in incorrect model binding. Consider renaming the parameter or using a model binding attribute to override the name.",
+                "Property on type '{0}' has the same name as parameter '{1}'. This may result in incorrect model binding. " +
+                "Consider renaming the parameter or the property to avoid conflicts. If the type '{0}' has a custom type converter or custom model binder, you can suppress this message.",
                 "Naming",
                 DiagnosticSeverity.Warning,
                 isEnabledByDefault: true,

+ 26 - 1
src/Mvc/Mvc.Analyzers/src/TopLevelParameterNameAnalyzer.cs

@@ -89,12 +89,17 @@ namespace Microsoft.AspNetCore.Mvc.Analyzers
                 return false;
             }
 
-            if (SpecifiesModelType(symbolCache, parameter))
+            if (SpecifiesModelType(in symbolCache, parameter))
             {
                 // Ignore parameters that specify a model type.
                 return false;
             }
 
+            if (!IsComplexType(parameter.Type))
+            {
+                return false;
+            }
+
             var parameterName = GetName(symbolCache, parameter);
 
             var type = parameter.Type;
@@ -122,6 +127,26 @@ namespace Microsoft.AspNetCore.Mvc.Analyzers
             return false;
         }
 
+        private static bool IsComplexType(ITypeSymbol type)
+        {
+            // This analyzer should not apply to simple types. In MVC, a simple type is any type that has a type converter that returns true for TypeConverter.CanConvertFrom(typeof(string)).
+            // Unfortunately there isn't a Roslyn way of determining if a TypeConverter exists for a given symbol or if the converter allows string conversions.
+            // https://github.com/dotnet/corefx/blob/v3.0.0-preview8.19405.3/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs#L103-L141
+            // provides a list of types that have built-in converters.
+            // We'll use a simpler heuristic in the analyzer: A type is simple if it's a value type or if it's in the "System.*" namespace hierarchy.
+
+            var @namespace = type.ContainingNamespace?.ToString();
+            if (@namespace != null)
+            {
+                // Things in the System.* namespace hierarchy don't count as complex types. This workarounds
+                // the problem of discovering type converters on types in mscorlib.
+                return @namespace != "System" &&
+                    [email protected]("System.", StringComparison.Ordinal);
+            }
+
+            return true;
+        }
+
         internal static string GetName(in SymbolCache symbolCache, ISymbol symbol)
         {
             foreach (var attribute in symbol.GetAttributes(symbolCache.IModelNameProvider))

+ 9 - 0
src/Mvc/Mvc.Analyzers/test/TestFiles/TopLevelParameterNameAnalyzerTest/IsProblematicParameter_ReturnsFalse_ForSimpleTypes.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace Microsoft.AspNetCore.Mvc.Analyzers.TopLevelParameterNameAnalyzerTestFiles
+{
+    public class IsProblematicParameter_ReturnsFalse_ForSimpleTypes
+    {
+        public void ActionMethod(DateTime date, DateTime? day, Uri absoluteUri, Version majorRevision, DayOfWeek sunday) { }
+    }
+}

+ 24 - 0
src/Mvc/Mvc.Analyzers/test/TopLevelParameterNameAnalyzerTest.cs

@@ -95,6 +95,30 @@ namespace Microsoft.AspNetCore.Mvc.Analyzers
             Assert.False(result);
         }
 
+        // Test for https://github.com/aspnet/AspNetCore/issues/6945
+        [Fact]
+        public async Task IsProblematicParameter_ReturnsFalse_ForSimpleTypes()
+        {
+            var testName = nameof(IsProblematicParameter_ReturnsFalse_ForSimpleTypes);
+            var testSource = MvcTestSource.Read(GetType().Name, testName);
+            var project = DiagnosticProject.Create(GetType().Assembly, new[] { testSource.Source });
+
+            var compilation = await project.GetCompilationAsync();
+
+            var modelType = compilation.GetTypeByMetadataName($"Microsoft.AspNetCore.Mvc.Analyzers.TopLevelParameterNameAnalyzerTestFiles.{testName}");
+            var method = (IMethodSymbol)modelType.GetMembers("ActionMethod").First();
+
+            Assert.True(TopLevelParameterNameAnalyzer.SymbolCache.TryCreate(compilation, out var symbolCache));
+
+            Assert.Collection(
+                method.Parameters,
+                p => Assert.False(TopLevelParameterNameAnalyzer.IsProblematicParameter(symbolCache, p)),
+                p => Assert.False(TopLevelParameterNameAnalyzer.IsProblematicParameter(symbolCache, p)),
+                p => Assert.False(TopLevelParameterNameAnalyzer.IsProblematicParameter(symbolCache, p)),
+                p => Assert.False(TopLevelParameterNameAnalyzer.IsProblematicParameter(symbolCache, p)),
+                p => Assert.False(TopLevelParameterNameAnalyzer.IsProblematicParameter(symbolCache, p)));
+        }
+
         [Fact]
         public async Task IsProblematicParameter_IgnoresStaticProperties()
         {

+ 3 - 1
src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Areas/Identity/Pages/Shared/_LoginPartial.cshtml

@@ -10,7 +10,9 @@
         <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity.Name!</a>
     </li>
     <li class="nav-item">
-        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/LogOut">Logout</a>
+        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="/" method="post">
+            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
+        </form>
     </li>
 }
 else

+ 1 - 1
src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/template.json

@@ -8,7 +8,7 @@
   ],
   "name": "ASP.NET Core Web App",
   "generatorVersions": "[1.0.0.0-*)",
-  "description": "A project template for creating an ASP.NET Core application with example ASP.NET Razor Pages content",
+  "description": "A project template for creating an ASP.NET Core application with example ASP.NET Core Razor Pages content",
   "groupIdentity": "Microsoft.Web.RazorPages",
   "precedence": "5000",
   "identity": "Microsoft.Web.RazorPages.CSharp.3.0",

+ 2 - 2
src/ProjectTemplates/test/BlazorServerTemplateTest.cs

@@ -36,7 +36,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();
@@ -93,7 +93,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();

+ 14 - 5
src/ProjectTemplates/test/EmptyWebTemplateTest.cs

@@ -22,10 +22,19 @@ namespace Templates.Test
 
         public ITestOutputHelper Output { get; }
 
-        [Theory]
-        [InlineData(null)]
-        [InlineData("F#")]
-        public async Task EmptyWebTemplateAsync(string languageOverride)
+        [Fact]
+        public async Task EmptyWebTemplateCSharp()
+        {
+            await EmtpyTemplateCore(languageOverride: null);
+        }
+
+        [Fact]
+        public async Task EmptyWebTemplateFSharp()
+        {
+            await EmtpyTemplateCore("F#");
+        }
+
+        private async Task EmtpyTemplateCore(string languageOverride)
         {
             Project = await ProjectFactory.GetOrCreateProject("empty" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output);
 
@@ -42,7 +51,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();

+ 27 - 5
src/ProjectTemplates/test/Helpers/AspNetProcess.cs

@@ -58,7 +58,7 @@ namespace Templates.Test.Helpers
 
             var arguments = published ? $"exec {dllPath}" : "run";
             Process = ProcessEx.Run(output, workingDirectory, DotNetMuxer.MuxerPathOrDefault(), arguments, envVars: environmentVariables);
-            if(hasListeningUri)
+            if (hasListeningUri)
             {
                 ListeningUri = GetListeningUri(output);
             }
@@ -108,7 +108,7 @@ namespace Templates.Test.Helpers
                 HttpMethod.Get,
                 new Uri(ListeningUri, page.Url));
 
-            var response = await _httpClient.SendAsync(request);
+            var response = await RequestWithRetries(client => client.SendAsync(request), _httpClient);
 
             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
             var parser = new HtmlParser();
@@ -141,7 +141,7 @@ namespace Templates.Test.Helpers
                     Assert.True(string.Equals(anchor.Href, expectedLink), $"Expected next link to be {expectedLink} but it was {anchor.Href}.");
                     var result = await RetryHelper.RetryRequest(async () =>
                     {
-                        return await _httpClient.GetAsync(anchor.Href);
+                        return await RequestWithRetries(client => client.GetAsync(anchor.Href), _httpClient);
                     }, logger: NullLogger.Instance);
 
                     Assert.True(IsSuccessStatusCode(result), $"{anchor.Href} is a broken link!");
@@ -149,6 +149,28 @@ namespace Templates.Test.Helpers
             }
         }
 
+        private async Task<T> RequestWithRetries<T>(Func<HttpClient, Task<T>> requester, HttpClient client, int retries = 3, TimeSpan initialDelay = default)
+        {
+            var currentDelay = initialDelay == default ? TimeSpan.FromSeconds(30) : initialDelay;
+            for (int i = 0; i <= retries; i++)
+            {
+                try
+                {
+                    return await requester(client);
+                }
+                catch (Exception)
+                {
+                    if (i == retries)
+                    {
+                        throw;
+                    }
+                    await Task.Delay(currentDelay);
+                    currentDelay *= 2;
+                }
+            }
+            throw new InvalidOperationException("Max retries reached.");
+        }
+
         private Uri GetListeningUri(ITestOutputHelper output)
         {
             // Wait until the app is accepting HTTP requests
@@ -190,7 +212,7 @@ namespace Templates.Test.Helpers
 
         internal Task<HttpResponseMessage> SendRequest(string path)
         {
-            return _httpClient.GetAsync(new Uri(ListeningUri, path));
+            return RequestWithRetries(client => client.GetAsync(new Uri(ListeningUri, path)), _httpClient);
         }
 
         public async Task AssertStatusCode(string requestUrl, HttpStatusCode statusCode, string acceptContentType = null)
@@ -204,7 +226,7 @@ namespace Templates.Test.Helpers
                 request.Headers.Add("Accept", acceptContentType);
             }
 
-            var response = await _httpClient.SendAsync(request);
+            var response = await RequestWithRetries(client => client.SendAsync(request), _httpClient);
             Assert.True(statusCode == response.StatusCode, $"Expected {requestUrl} to have status '{statusCode}' but it was '{response.StatusCode}'.");
         }
 

+ 1 - 1
src/ProjectTemplates/test/IdentityUIPackageTest.cs

@@ -134,7 +134,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync(packageOptions: packageOptions);

+ 11 - 9
src/ProjectTemplates/test/MvcTemplateTest.cs

@@ -25,11 +25,14 @@ namespace Templates.Test
         public ProjectFactoryFixture ProjectFactory { get; }
         public ITestOutputHelper Output { get; }
 
-        [Theory]
-        [InlineData(null)]
-        [InlineData("F#")]
-        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2267", FlakyOn.All)]
-        public async Task MvcTemplate_NoAuthImplAsync(string languageOverride)
+        [Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/14022")]
+        public async Task MvcTemplate_NoAuthFSharp() => await MvcTemplateCore(languageOverride: "F#");
+
+        [Fact]
+        public async Task MvcTemplate_NoAuthCSharp() => await MvcTemplateCore(languageOverride: null);
+
+
+        private async Task MvcTemplateCore(string languageOverride)
         {
             Project = await ProjectFactory.GetOrCreateProject("mvcnoauth" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output);
 
@@ -54,7 +57,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();
@@ -104,8 +107,7 @@ namespace Templates.Test
         [Theory]
         [InlineData(true)]
         [InlineData(false)]
-        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2267", FlakyOn.All)]
-        public async Task MvcTemplate_IndividualAuthImplAsync(bool useLocalDB)
+        public async Task MvcTemplate_IndividualAuth(bool useLocalDB)
         {
             Project = await ProjectFactory.GetOrCreateProject("mvcindividual" + (useLocalDB ? "uld" : ""), Output);
 
@@ -122,7 +124,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();

+ 2 - 2
src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs

@@ -33,7 +33,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();
@@ -52,7 +52,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();

+ 4 - 6
src/ProjectTemplates/test/RazorPagesTemplateTest.cs

@@ -26,8 +26,7 @@ namespace Templates.Test
         public ITestOutputHelper Output { get; }
 
         [Fact]
-        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2327", FlakyOn.All)]
-        public async Task RazorPagesTemplate_NoAuthImplAsync()
+        public async Task RazorPagesTemplate_NoAuth()
         {
             Project = await ProjectFactory.GetOrCreateProject("razorpagesnoauth", Output);
 
@@ -45,7 +44,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, createResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();
@@ -95,10 +94,9 @@ namespace Templates.Test
         }
 
         [Theory]
-        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2335", FlakyOn.All)]
         [InlineData(false)]
         [InlineData(true)]
-        public async Task RazorPagesTemplate_IndividualAuthImplAsync(bool useLocalDB)
+        public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB)
         {
             Project = await ProjectFactory.GetOrCreateProject("razorpagesindividual" + (useLocalDB ? "uld" : ""), Output);
 
@@ -115,7 +113,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();

+ 1 - 1
src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs

@@ -74,7 +74,7 @@ namespace Templates.Test.SpaTemplateTest
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             using var buildResult = await Project.RunDotNetBuildAsync();

+ 8 - 5
src/ProjectTemplates/test/WebApiTemplateTest.cs

@@ -22,10 +22,13 @@ namespace Templates.Test
 
         public Project Project { get; set; }
 
-        [Theory]
-        [InlineData(null)]
-        [InlineData("F#")]
-        public async Task WebApiTemplateAsync(string languageOverride)
+        [Fact]
+        public async Task WebApiTemplateFSharp() => await WebApiTemplateCore(languageOverride: "F#");
+
+        [Fact]
+        public async Task WebApiTemplateCSharp() => await WebApiTemplateCore(languageOverride: null);
+
+        private async Task WebApiTemplateCore(string languageOverride)
         {
             Project = await FactoryFixture.GetOrCreateProject("webapi" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output);
 
@@ -42,7 +45,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();

+ 1 - 1
src/ProjectTemplates/test/WorkerTemplateTest.cs

@@ -32,7 +32,7 @@ namespace Templates.Test
             Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
 
             // Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
-            // The output from publish will go into bin/Release/netcoreapp5.0/publish and won't be affected by calling build
+            // The output from publish will go into bin/Release/netcoreappX.Y/publish and won't be affected by calling build
             // later, while the opposite is not true.
 
             var buildResult = await Project.RunDotNetBuildAsync();

+ 1 - 1
src/Servers/IIS/IntegrationTesting.IIS/src/IISExpressDeployer.cs

@@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
                 // Start timer
                 StartTimer();
 
-                // For an unpublished application the dllroot points pre-built dlls like projectdir/bin/debug/netcoreapp5.0/
+                // For an unpublished application the dllroot points pre-built dlls like projectdir/bin/debug/netcoreappX.Y/
                 // and contentRoot points to the project directory so you get things like static assets.
                 // For a published app both point to the publish directory.
                 var dllRoot = CheckIfPublishIsRequired();

+ 2 - 1
src/SignalR/common/Http.Connections/src/Internal/Transports/WebSocketsServerTransport.cs

@@ -155,7 +155,8 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal.Transports
                     var memory = _application.Output.GetMemory();
 
                     var receiveResult = await socket.ReceiveAsync(memory, token);
-                    // Need to check again for netcoreapp5.0 because a close can happen between a 0-byte read and the actual read
+
+                    // Need to check again for netcoreapp3.0 and later because a close can happen between a 0-byte read and the actual read
                     if (receiveResult.MessageType == WebSocketMessageType.Close)
                     {
                         return;