Przeglądaj źródła

Enable CA1835-CA1841 (#33270)

* Enable CA1835-CA1841, CA1845, CA1846
Pranav K 4 lat temu
rodzic
commit
ba6edfeab0
35 zmienionych plików z 152 dodań i 78 usunięć
  1. 35 0
      .editorconfig
  2. 1 1
      src/Components/WebAssembly/Server/src/DebugProxyLauncher.cs
  3. 6 3
      src/Http/Http/src/Internal/ReferenceReadStream.cs
  4. 2 2
      src/Http/Shared/StreamCopyOperationInternal.cs
  5. 11 6
      src/Http/WebUtilities/src/BufferedReadStream.cs
  6. 11 5
      src/Http/WebUtilities/src/FileBufferingWriteStream.cs
  7. 2 8
      src/Http/WebUtilities/src/HttpRequestStreamReader.cs
  8. 1 1
      src/Http/WebUtilities/src/HttpResponseStreamWriter.cs
  9. 9 11
      src/Http/WebUtilities/src/PagedByteBuffer.cs
  10. 2 0
      src/Http/WebUtilities/src/PublicAPI.Unshipped.txt
  11. 3 2
      src/Http/WebUtilities/src/StreamHelperExtensions.cs
  12. 4 1
      src/Http/WebUtilities/test/HttpResponseStreamWriterTest.cs
  13. 1 1
      src/Middleware/HttpLogging/src/RequestBufferingStream.cs
  14. 7 4
      src/Middleware/ResponseCaching/src/Streams/ResponseCachingStream.cs
  15. 5 2
      src/Middleware/ResponseCompression/src/ResponseCompressionBody.cs
  16. 2 2
      src/Middleware/WebSockets/test/UnitTests/BufferStream.cs
  17. 1 1
      src/Mvc/Mvc.Core/test/DependencyInjection/MvcCoreServiceCollectionExtensionsTest.cs
  18. 4 1
      src/Mvc/Mvc.ViewFeatures/test/ViewExecutorTest.cs
  19. 2 2
      src/Mvc/Mvc/test/MvcServiceCollectionExtensionsTest.cs
  20. 4 1
      src/Servers/HttpSys/src/ResponseStream.cs
  21. 1 1
      src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs
  22. 6 4
      src/Servers/IIS/IntegrationTesting.IIS/src/IISExpressDeployer.cs
  23. 2 1
      src/Servers/IIS/IntegrationTesting.IIS/src/LoggingHandler.cs
  24. 1 1
      src/Servers/IIS/IntegrationTesting.IIS/src/ProcessTracker.cs
  25. 1 1
      src/Servers/Kestrel/Core/src/Middleware/Internal/LoggingStream.cs
  26. 1 1
      src/Servers/Kestrel/samples/SampleApp/Startup.cs
  27. 1 1
      src/Servers/Kestrel/samples/SystemdTestApp/Startup.cs
  28. 8 8
      src/SignalR/common/Http.Connections/src/ServerSentEventsMessageFormatter.cs
  29. 8 0
      src/SignalR/common/Shared/MemoryBufferWriter.cs
  30. 2 2
      src/SignalR/common/Shared/StreamExtensions.cs
  31. 1 1
      src/SignalR/perf/benchmarkapps/Crankier/Agent.cs
  32. 1 1
      src/SignalR/perf/benchmarkapps/Crankier/Worker.cs
  33. 1 1
      src/SignalR/server/Core/src/Internal/HubGroupList.cs
  34. 1 1
      src/Tools/Microsoft.dotnet-openapi/src/DebugMode.cs
  35. 4 0
      src/Tools/Shared/CommandLine/DebugHelper.cs

+ 35 - 0
.editorconfig

@@ -125,6 +125,33 @@ dotnet_diagnostic.CA1833.severity = warning
 # CA1834: Consider using 'StringBuilder.Append(char)' when applicable
 dotnet_diagnostic.CA1834.severity = warning
 
+# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
+dotnet_diagnostic.CA1835.severity = warning
+
+# CA1836: Prefer IsEmpty over Count
+dotnet_diagnostic.CA1836.severity = warning
+
+# CA1837: Use 'Environment.ProcessId'
+dotnet_diagnostic.CA1837.severity = warning
+
+# CA1838: Avoid 'StringBuilder' parameters for P/Invokes
+dotnet_diagnostic.CA1838.severity = warning
+
+# CA1839: Use 'Environment.ProcessPath'
+dotnet_diagnostic.CA1839.severity = warning
+
+# CA1840: Use 'Environment.CurrentManagedThreadId'
+dotnet_diagnostic.CA1840.severity = warning
+
+# CA1841: Prefer Dictionary.Contains methods
+dotnet_diagnostic.CA1841.severity = warning
+
+# CA1845: Use span-based 'string.Concat'
+dotnet_diagnostic.CA1845.severity = warning
+
+# CA1846: Prefer AsSpan over Substring
+dotnet_diagnostic.CA1846.severity = warning
+
 # CA2012: Use ValueTask correctly
 dotnet_diagnostic.CA2012.severity = warning
 
@@ -151,5 +178,13 @@ dotnet_diagnostic.CA1827.severity = suggestion
 dotnet_diagnostic.CA1829.severity = suggestion
 # CA1834: Consider using 'StringBuilder.Append(char)' when applicable
 dotnet_diagnostic.CA1834.severity = suggestion
+# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
+dotnet_diagnostic.CA1835.severity = suggestion
+# CA1837: Use 'Environment.ProcessId'
+dotnet_diagnostic.CA1837.severity = suggestion
+# CA1838: Avoid 'StringBuilder' parameters for P/Invokes
+dotnet_diagnostic.CA1838.severity = suggestion
+# CA1841: Prefer Dictionary.Contains methods
+dotnet_diagnostic.CA1841.severity = suggestion
 # CA2012: Use ValueTask correctly
 dotnet_diagnostic.CA2012.severity = suggestion

+ 1 - 1
src/Components/WebAssembly/Server/src/DebugProxyLauncher.cs

@@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Builder
             var environment = serviceProvider.GetRequiredService<IWebHostEnvironment>();
             var executablePath = LocateDebugProxyExecutable(environment);
             var muxerPath = DotNetMuxer.MuxerPathOrDefault();
-            var ownerPid = Process.GetCurrentProcess().Id;
+            var ownerPid = Environment.ProcessId;
 
             var processStartInfo = new ProcessStartInfo
             {

+ 6 - 3
src/Http/Http/src/Internal/ReferenceReadStream.cs

@@ -106,12 +106,15 @@ namespace Microsoft.AspNetCore.Http
             return read;
         }
 
-        public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+        public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+            => ReadAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask();
+
+        public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken)
         {
             ThrowIfDisposed();
             VerifyPosition();
-            var toRead = Math.Min(count, _length - _position);
-            var read = await _inner.ReadAsync(buffer, offset, (int)toRead, cancellationToken);
+            var toRead = (int)Math.Min(buffer.Length, _length - _position);
+            var read = await _inner.ReadAsync(buffer.Slice(0, toRead), cancellationToken);
             _position += read;
             return read;
         }

+ 2 - 2
src/Http/Shared/StreamCopyOperationInternal.cs

@@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Http
                     {
                         readLength = (int)Math.Min(bytesRemaining.GetValueOrDefault(), (long)readLength);
                     }
-                    int read = await source.ReadAsync(buffer, 0, readLength, cancel);
+                    int read = await source.ReadAsync(buffer.AsMemory(0, readLength), cancel);
 
                     if (bytesRemaining.HasValue)
                     {
@@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Http
 
                     cancel.ThrowIfCancellationRequested();
 
-                    await destination.WriteAsync(buffer, 0, read, cancel);
+                    await destination.WriteAsync(buffer.AsMemory(0, read), cancel);
                 }
             }
             finally

+ 11 - 6
src/Http/WebUtilities/src/BufferedReadStream.cs

@@ -218,21 +218,26 @@ namespace Microsoft.AspNetCore.WebUtilities
         }
 
         /// <inheritdoc/>
-        public async override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+        public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
         {
             ValidateBuffer(buffer, offset, count);
+            return ReadAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask();
+        }
 
+        /// <inheritdoc/>
+        public async override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken)
+        {
             // Drain buffer
             if (_bufferCount > 0)
             {
-                int toCopy = Math.Min(_bufferCount, count);
-                Buffer.BlockCopy(_buffer, _bufferOffset, buffer, offset, toCopy);
+                int toCopy = Math.Min(_bufferCount, buffer.Length);
+                _buffer.AsMemory(_bufferOffset, toCopy).CopyTo(buffer);
                 _bufferOffset += toCopy;
                 _bufferCount -= toCopy;
                 return toCopy;
             }
 
-            return await _inner.ReadAsync(buffer, offset, count, cancellationToken);
+            return await _inner.ReadAsync(buffer, cancellationToken);
         }
 
         /// <summary>
@@ -264,7 +269,7 @@ namespace Microsoft.AspNetCore.WebUtilities
             }
             // Downshift to make room
             _bufferOffset = 0;
-            _bufferCount = await _inner.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken);
+            _bufferCount = await _inner.ReadAsync(_buffer.AsMemory(), cancellationToken);
             return _bufferCount > 0;
         }
 
@@ -323,7 +328,7 @@ namespace Microsoft.AspNetCore.WebUtilities
                     }
                     _bufferOffset = 0;
                 }
-                int read = await _inner.ReadAsync(_buffer, _bufferOffset + _bufferCount, _buffer.Length - _bufferCount - _bufferOffset, cancellationToken);
+                int read = await _inner.ReadAsync(_buffer.AsMemory(_bufferOffset + _bufferCount, _buffer.Length - _bufferCount - _bufferOffset), cancellationToken);
                 _bufferCount += read;
                 if (read == 0)
                 {

+ 11 - 5
src/Http/WebUtilities/src/FileBufferingWriteStream.cs

@@ -142,20 +142,27 @@ namespace Microsoft.AspNetCore.WebUtilities
         public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
         {
             ThrowArgumentException(buffer, offset, count);
+            await WriteAsync(buffer.AsMemory(offset, count), cancellationToken);
+        }
+
+        /// <inheritdoc />
+        [SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads", Justification = "This is a method overload.")]
+        public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
+        {
             ThrowIfDisposed();
 
-            if (_bufferLimit.HasValue && _bufferLimit - Length < count)
+            if (_bufferLimit.HasValue && _bufferLimit - Length < buffer.Length)
             {
                 Dispose();
                 throw new IOException("Buffer limit exceeded.");
             }
 
             // Allow buffering in memory if we're below the memory threshold once the current buffer is written.
-            var allowMemoryBuffer = (_memoryThreshold - count) >= PagedByteBuffer.Length;
+            var allowMemoryBuffer = (_memoryThreshold - buffer.Length) >= PagedByteBuffer.Length;
             if (allowMemoryBuffer)
             {
                 // Buffer content in the MemoryStream if it has capacity.
-                PagedByteBuffer.Add(buffer, offset, count);
+                PagedByteBuffer.Add(buffer);
                 Debug.Assert(PagedByteBuffer.Length <= _memoryThreshold);
             }
             else
@@ -166,7 +173,7 @@ namespace Microsoft.AspNetCore.WebUtilities
 
                 // Spool memory content to disk.
                 await PagedByteBuffer.MoveToAsync(FileStream, cancellationToken);
-                await FileStream.WriteAsync(buffer, offset, count, cancellationToken);
+                await FileStream.WriteAsync(buffer, cancellationToken);
             }
         }
 
@@ -188,7 +195,6 @@ namespace Microsoft.AspNetCore.WebUtilities
         /// <param name="destination">The <see cref="Stream" /> to drain buffered contents to.</param>
         /// <param name="cancellationToken">The <see cref="CancellationToken" />.</param>
         /// <returns>A <see cref="Task" /> that represents the asynchronous drain operation.</returns>
-        [SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Required to maintain compatibility")]
         public async Task DrainBufferAsync(Stream destination, CancellationToken cancellationToken = default)
         {
             // When not null, FileStream always has "older" spooled content. The PagedByteBuffer always has "newer"

+ 2 - 8
src/Http/WebUtilities/src/HttpRequestStreamReader.cs

@@ -294,10 +294,7 @@ namespace Microsoft.AspNetCore.WebUtilities
                     do
                     {
                         Debug.Assert(charsRemaining == 0);
-                        _bytesRead = await _stream.ReadAsync(
-                            _byteBuffer,
-                            0,
-                            _byteBufferSize);
+                        _bytesRead = await _stream.ReadAsync(_byteBuffer.AsMemory(0, _byteBufferSize));
                         if (_bytesRead == 0)  // EOF
                         {
                             _isBlocked = true;
@@ -534,10 +531,7 @@ namespace Microsoft.AspNetCore.WebUtilities
 
             do
             {
-                _bytesRead = await _stream.ReadAsync(
-                    _byteBuffer,
-                    0,
-                    _byteBufferSize).ConfigureAwait(false);
+                _bytesRead = await _stream.ReadAsync(_byteBuffer.AsMemory(0, _byteBufferSize)).ConfigureAwait(false);
                 if (_bytesRead == 0)
                 {
                     // We're at EOF

+ 1 - 1
src/Http/WebUtilities/src/HttpResponseStreamWriter.cs

@@ -530,7 +530,7 @@ namespace Microsoft.AspNetCore.WebUtilities
 
             if (count > 0)
             {
-                await _stream.WriteAsync(_byteBuffer, 0, count);
+                await _stream.WriteAsync(_byteBuffer.AsMemory(0, count));
             }
         }
 

+ 9 - 11
src/Http/WebUtilities/src/PagedByteBuffer.cs

@@ -46,25 +46,23 @@ namespace Microsoft.AspNetCore.WebUtilities
         }
 
         public void Add(byte[] buffer, int offset, int count)
+            => Add(buffer.AsMemory(offset, count));
+
+        public void Add(ReadOnlyMemory<byte> memory)
         {
             ThrowIfDisposed();
 
-            while (count > 0)
+            while (!memory.IsEmpty)
             {
                 var currentPage = CurrentPage;
-                var copyLength = Math.Min(count, currentPage.Length - _currentPageIndex);
+                var copyLength = Math.Min(memory.Length, currentPage.Length - _currentPageIndex);
 
-                Buffer.BlockCopy(
-                    buffer,
-                    offset,
-                    currentPage,
-                    _currentPageIndex,
-                    copyLength);
+                memory.Slice(0, copyLength).CopyTo(currentPage.AsMemory(_currentPageIndex, copyLength));
 
                 Length += copyLength;
                 _currentPageIndex += copyLength;
-                offset += copyLength;
-                count -= copyLength;
+
+                memory = memory.Slice(copyLength);
             }
         }
 
@@ -113,7 +111,7 @@ namespace Microsoft.AspNetCore.WebUtilities
                     _currentPageIndex :
                     page.Length;
 
-                await stream.WriteAsync(page, 0, length, cancellationToken);
+                await stream.WriteAsync(page.AsMemory(0, length), cancellationToken);
             }
 
             ClearBuffers();

+ 2 - 0
src/Http/WebUtilities/src/PublicAPI.Unshipped.txt

@@ -2,6 +2,8 @@
 *REMOVED*static Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseNullableQuery(string! queryString) -> System.Collections.Generic.Dictionary<string!, Microsoft.Extensions.Primitives.StringValues>?
 Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.MemoryThreshold.get -> int
 Microsoft.AspNetCore.WebUtilities.FileBufferingWriteStream.MemoryThreshold.get -> int
+override Microsoft.AspNetCore.WebUtilities.BufferedReadStream.ReadAsync(System.Memory<byte> buffer, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.ValueTask<int>
+override Microsoft.AspNetCore.WebUtilities.FileBufferingWriteStream.WriteAsync(System.ReadOnlyMemory<byte> buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.ValueTask
 static Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseNullableQuery(string? queryString) -> System.Collections.Generic.Dictionary<string!, Microsoft.Extensions.Primitives.StringValues>?
 *REMOVED*static Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(string! queryString) -> System.Collections.Generic.Dictionary<string!, Microsoft.Extensions.Primitives.StringValues>!
 static Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(string? queryString) -> System.Collections.Generic.Dictionary<string!, Microsoft.Extensions.Primitives.StringValues>!

+ 3 - 2
src/Http/WebUtilities/src/StreamHelperExtensions.cs

@@ -1,6 +1,7 @@
 // Copyright (c) .NET Foundation. All rights reserved.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
+using System;
 using System.Buffers;
 using System.IO;
 using System.Threading;
@@ -62,7 +63,7 @@ namespace Microsoft.AspNetCore.WebUtilities
             long total = 0;
             try
             {
-                var read = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
+                var read = await stream.ReadAsync(buffer.AsMemory(), cancellationToken);
                 while (read > 0)
                 {
                     // Not all streams support cancellation directly.
@@ -72,7 +73,7 @@ namespace Microsoft.AspNetCore.WebUtilities
                         throw new InvalidDataException($"The stream exceeded the data limit {limit.GetValueOrDefault()}.");
                     }
                     total += read;
-                    read = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
+                    read = await stream.ReadAsync(buffer.AsMemory(), cancellationToken);
                 }
             }
             finally

+ 4 - 1
src/Http/WebUtilities/test/HttpResponseStreamWriterTest.cs

@@ -663,13 +663,16 @@ namespace Microsoft.AspNetCore.WebUtilities
             }
 
             public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+                => WriteAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask();
+
+            public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
             {
                 WriteAsyncCallCount++;
                 if (ThrowOnWrite)
                 {
                     throw new IOException("Test IOException");
                 }
-                return base.WriteAsync(buffer, offset, count, cancellationToken);
+                return base.WriteAsync(buffer, cancellationToken);
             }
 
             protected override void Dispose(bool disposing)

+ 1 - 1
src/Middleware/HttpLogging/src/RequestBufferingStream.cs

@@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.HttpLogging
 
         public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
         {
-            var res = await _innerStream.ReadAsync(buffer, offset, count, cancellationToken);
+            var res = await _innerStream.ReadAsync(buffer.AsMemory(offset, count), cancellationToken);
 
             WriteToBuffer(buffer.AsSpan(offset, res));
 

+ 7 - 4
src/Middleware/ResponseCaching/src/Streams/ResponseCachingStream.cs

@@ -130,12 +130,15 @@ namespace Microsoft.AspNetCore.ResponseCaching
             }
         }
 
-        public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+        public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) =>
+            await WriteAsync(buffer.AsMemory(offset, count));
+
+        public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
         {
             try
             {
                 _startResponseCallback();
-                await _innerStream.WriteAsync(buffer, offset, count, cancellationToken);
+                await _innerStream.WriteAsync(buffer, cancellationToken);
             }
             catch
             {
@@ -145,13 +148,13 @@ namespace Microsoft.AspNetCore.ResponseCaching
 
             if (BufferingEnabled)
             {
-                if (_segmentWriteStream.Length + count > _maxBufferSize)
+                if (_segmentWriteStream.Length + buffer.Length > _maxBufferSize)
                 {
                     DisableBuffering();
                 }
                 else
                 {
-                    await _segmentWriteStream.WriteAsync(buffer, offset, count, cancellationToken);
+                    await _segmentWriteStream.WriteAsync(buffer, cancellationToken);
                 }
             }
         }

+ 5 - 2
src/Middleware/ResponseCompression/src/ResponseCompressionBody.cs

@@ -180,12 +180,15 @@ namespace Microsoft.AspNetCore.ResponseCompression
             => TaskToApm.End(asyncResult);
 
         public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+            => await WriteAsync(buffer.AsMemory(offset, count), cancellationToken);
+
+        public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
         {
             OnWrite();
 
             if (_compressionStream != null)
             {
-                await _compressionStream.WriteAsync(buffer, offset, count, cancellationToken);
+                await _compressionStream.WriteAsync(buffer, cancellationToken);
                 if (_autoFlush)
                 {
                     await _compressionStream.FlushAsync(cancellationToken);
@@ -193,7 +196,7 @@ namespace Microsoft.AspNetCore.ResponseCompression
             }
             else
             {
-                await _innerStream.WriteAsync(buffer, offset, count, cancellationToken);
+                await _innerStream.WriteAsync(buffer, cancellationToken);
             }
         }
 

+ 2 - 2
src/Middleware/WebSockets/test/UnitTests/BufferStream.cs

@@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test
                     offset += actualCount;
                     count -= actualCount;
                 }
-                while (count > 0 && (_topBuffer.Count > 0 || _bufferedData.Count > 0));
+                while (count > 0 && (_topBuffer.Count > 0 || !_bufferedData.IsEmpty));
                 // Keep reading while there is more data available and we have more space to put it in.
                 return totalRead;
             }
@@ -206,7 +206,7 @@ namespace Microsoft.AspNetCore.WebSockets.Test
                     offset += actualCount;
                     count -= actualCount;
                 }
-                while (count > 0 && (_topBuffer.Count > 0 || _bufferedData.Count > 0));
+                while (count > 0 && (_topBuffer.Count > 0 || !_bufferedData.IsEmpty));
                 // Keep reading while there is more data available and we have more space to put it in.
                 return totalRead;
             }

+ 1 - 1
src/Mvc/Mvc.Core/test/DependencyInjection/MvcCoreServiceCollectionExtensionsTest.cs

@@ -224,7 +224,7 @@ namespace Microsoft.AspNetCore.Mvc
 
                 var multiRegistrationServiceTypes = MultiRegistrationServiceTypes;
                 return services
-                    .Where(sd => !multiRegistrationServiceTypes.Keys.Contains(sd.ServiceType))
+                    .Where(sd => !multiRegistrationServiceTypes.ContainsKey(sd.ServiceType))
                     .Select(sd => sd.ServiceType);
             }
         }

+ 4 - 1
src/Mvc/Mvc.ViewFeatures/test/ViewExecutorTest.cs

@@ -374,8 +374,11 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
             // Assert
             stream.Verify(s => s.FlushAsync(It.IsAny<CancellationToken>()), Times.Never());
             stream.Verify(
-                s => s.WriteAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()),
+                s => s.WriteAsync(It.IsAny<ReadOnlyMemory<byte>>(), It.IsAny<CancellationToken>()),
                 Times.Exactly((int)expectedWriteCallCount));
+            stream.Verify(
+                s => s.WriteAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()),
+                Times.Never());
             stream.Verify(s => s.Write(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()), Times.Never());
         }
 

+ 2 - 2
src/Mvc/Mvc/test/MvcServiceCollectionExtensionsTest.cs

@@ -443,7 +443,7 @@ namespace Microsoft.AspNetCore.Mvc
 
                 var multiRegistrationServiceTypes = MultiRegistrationServiceTypes;
                 return services
-                    .Where(sd => !multiRegistrationServiceTypes.Keys.Contains(sd.ServiceType))
+                    .Where(sd => !multiRegistrationServiceTypes.ContainsKey(sd.ServiceType))
                     .Where(sd => sd.ServiceType.Assembly.FullName.Contains("Mvc"))
                     .Select(sd => sd.ServiceType);
             }
@@ -601,7 +601,7 @@ namespace Microsoft.AspNetCore.Mvc
             Assert.True(
                 (expectedServiceRegistrationCount == actual),
                 $"Expected service type '{serviceType}' to be registered {expectedServiceRegistrationCount}" +
-                $" time(s) but was actually registered {actual} time(s)." + 
+                $" time(s) but was actually registered {actual} time(s)." +
                 string.Join(Environment.NewLine, serviceDescriptors.Select(sd => sd.ImplementationType)));
         }
 

+ 4 - 1
src/Servers/HttpSys/src/ResponseStream.cs

@@ -67,9 +67,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
         }
 
         public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+            => await WriteAsync(buffer.AsMemory(offset, count), cancellationToken);
+
+        public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
         {
             await _onStart();
-            await _innerStream.WriteAsync(buffer, offset, count, cancellationToken);
+            await _innerStream.WriteAsync(buffer, cancellationToken);
         }
 
         public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state)

+ 1 - 1
src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs

@@ -1040,7 +1040,7 @@ namespace TestSite
 
         private async Task ProcessId(HttpContext context)
         {
-            await context.Response.WriteAsync(Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture));
+            await context.Response.WriteAsync(Environment.ProcessId.ToString(CultureInfo.InvariantCulture));
         }
 
         public async Task ANCM_HTTPS_PORT(HttpContext context)

+ 6 - 4
src/Servers/IIS/IntegrationTesting.IIS/src/IISExpressDeployer.cs

@@ -457,7 +457,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
             [DllImport("user32.dll")]
             internal static extern bool EnumWindows(EnumWindowProc callback, IntPtr lParam);
             [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
-            internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName,int nMaxCount);
+            internal static extern int GetClassName(IntPtr hWnd, char[] lpClassName,int nMaxCount);
         }
 
         private void SendStopMessageToProcess(int pid)
@@ -480,14 +480,16 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
                     if (pid == windowProcessId)
                     {
                         // 256 is the max length
-                        var className = new StringBuilder(256);
+                        char[] buffer = new char[256];
+                        var length = WindowsNativeMethods.GetClassName(ptr, buffer, buffer.Length);
 
-                        if (WindowsNativeMethods.GetClassName(ptr, className, className.Capacity) == 0)
+                        if (length == 0)
                         {
                             throw new InvalidOperationException($"Unable to get window class name: {Marshal.GetLastWin32Error()}");
                         }
 
-                        if (!string.Equals(className.ToString(), "IISEXPRESS", StringComparison.OrdinalIgnoreCase))
+                        var className = new string(buffer, 0, length);
+                        if (!string.Equals(className, "IISEXPRESS", StringComparison.OrdinalIgnoreCase))
                         {
                             Logger.LogDebug($"Skipping window {ptr} with class name {className}");
                             // skip windows without IISEXPRESS class

+ 2 - 1
src/Servers/IIS/IntegrationTesting.IIS/src/LoggingHandler.cs

@@ -1,6 +1,7 @@
 // Copyright (c) .NET Foundation. All rights reserved.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
+using System;
 using System.Net.Http;
 using System.Text;
 using System.Threading;
@@ -43,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
                 var count = 0;
                 do
                 {
-                    count = await readAsStreamAsync.ReadAsync(buffer, offset, buffer.Length - offset);
+                    count = await readAsStreamAsync.ReadAsync(buffer.AsMemory(offset));
                     offset += count;
                 } while (count != 0 && offset != buffer.Length);
 

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

@@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
             }
 
             // Job name is optional but helps with diagnostics.  Job name must be unique if non-null.
-            _jobHandle = CreateJobObject(IntPtr.Zero, name: $"ProcessTracker{Process.GetCurrentProcess().Id}");
+            _jobHandle = CreateJobObject(IntPtr.Zero, name: $"ProcessTracker{Environment.ProcessId}");
 
             var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
             {

+ 1 - 1
src/Servers/Kestrel/Core/src/Middleware/Internal/LoggingStream.cs

@@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
 
         public async override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
         {
-            int read = await _inner.ReadAsync(buffer, offset, count, cancellationToken);
+            int read = await _inner.ReadAsync(buffer.AsMemory(offset, count), cancellationToken);
             Log("ReadAsync", new ReadOnlySpan<byte>(buffer, offset, read));
             return read;
         }

+ 1 - 1
src/Servers/Kestrel/samples/SampleApp/Startup.cs

@@ -155,7 +155,7 @@ namespace SampleApp
                         .UseContentRoot(Directory.GetCurrentDirectory())
                         .UseStartup<Startup>();
 
-                    if (string.Equals(Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture), Environment.GetEnvironmentVariable("LISTEN_PID")))
+                    if (string.Equals(Environment.ProcessId.ToString(CultureInfo.InvariantCulture), Environment.GetEnvironmentVariable("LISTEN_PID")))
                     {
                         // Use libuv if activated by systemd, since that's currently the only transport that supports being passed a socket handle.
 #pragma warning disable CS0618

+ 1 - 1
src/Servers/Kestrel/samples/SystemdTestApp/Startup.cs

@@ -73,7 +73,7 @@ namespace SystemdTestApp
                         .UseContentRoot(Directory.GetCurrentDirectory())
                         .UseStartup<Startup>();
 
-                    if (string.Equals(Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture), Environment.GetEnvironmentVariable("LISTEN_PID")))
+                    if (string.Equals(Environment.ProcessId.ToString(CultureInfo.InvariantCulture), Environment.GetEnvironmentVariable("LISTEN_PID")))
                     {
                         // Use libuv if activated by systemd, since that's currently the only transport that supports being passed a socket handle.
 #pragma warning disable CS0618

+ 8 - 8
src/SignalR/common/Http.Connections/src/ServerSentEventsMessageFormatter.cs

@@ -11,8 +11,8 @@ namespace Microsoft.AspNetCore.Http.Connections
 {
     internal static class ServerSentEventsMessageFormatter
     {
-        private static readonly byte[] DataPrefix = { (byte)'d', (byte)'a', (byte)'t', (byte)'a', (byte)':', (byte)' ' };
-        private static readonly byte[] Newline = { (byte)'\r', (byte)'\n' };
+        private static readonly ReadOnlyMemory<byte> DataPrefix = new[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a', (byte)':', (byte)' ' };
+        private static readonly ReadOnlyMemory<byte> Newline = new[] { (byte)'\r', (byte)'\n' };
 
         private const byte LineFeed = (byte)'\n';
 
@@ -23,12 +23,12 @@ namespace Microsoft.AspNetCore.Http.Connections
             {
                 if (payload.Length > 0)
                 {
-                    await output.WriteAsync(DataPrefix, 0, DataPrefix.Length, token);
+                    await output.WriteAsync(DataPrefix, token);
                     await output.WriteAsync(payload, token);
-                    await output.WriteAsync(Newline, 0, Newline.Length, token);
+                    await output.WriteAsync(Newline, token);
                 }
 
-                await output.WriteAsync(Newline, 0, Newline.Length, token);
+                await output.WriteAsync(Newline, token);
                 return;
             }
 
@@ -100,12 +100,12 @@ namespace Microsoft.AspNetCore.Http.Connections
                 }
 
                 // Write line
-                await output.WriteAsync(DataPrefix, 0, DataPrefix.Length);
+                await output.WriteAsync(DataPrefix);
                 await output.WriteAsync(lineSegment);
-                await output.WriteAsync(Newline, 0, Newline.Length);
+                await output.WriteAsync(Newline);
             }
 
-            await output.WriteAsync(Newline, 0, Newline.Length);
+            await output.WriteAsync(Newline);
         }
     }
 }

+ 8 - 0
src/SignalR/common/Shared/MemoryBufferWriter.cs

@@ -197,13 +197,21 @@ namespace Microsoft.AspNetCore.Internal
                 for (var i = 0; i < count; i++)
                 {
                     var segment = _completedSegments[i];
+#if NETCOREAPP
+                    await destination.WriteAsync(segment.Buffer.AsMemory(0, segment.Length));
+#else
                     await destination.WriteAsync(segment.Buffer, 0, segment.Length);
+#endif
                 }
             }
 
             if (_currentSegment is not null)
             {
+#if NETCOREAPP
+                await destination.WriteAsync(_currentSegment.AsMemory(0, _position));
+#else
                 await destination.WriteAsync(_currentSegment, 0, _position);
+#endif
             }
         }
 

+ 2 - 2
src/SignalR/common/Shared/StreamExtensions.cs

@@ -15,7 +15,7 @@ namespace System.IO
         {
             if (buffer.IsSingleSegment)
             {
-#if NETCOREAPP
+#if NETCOREAPP || NETSTANDARD2_1
                 return stream.WriteAsync(buffer.First, cancellationToken);
 #else
                 var isArray = MemoryMarshal.TryGetArray(buffer.First, out var arraySegment);
@@ -33,7 +33,7 @@ namespace System.IO
             var position = buffer.Start;
             while (buffer.TryGet(ref position, out var segment))
             {
-#if NETCOREAPP
+#if NETCOREAPP || NETSTANDARD2_1
                 await stream.WriteAsync(segment, cancellationToken);
 #else
                 var isArray = MemoryMarshal.TryGetArray(segment, out var arraySegment);

+ 1 - 1
src/SignalR/perf/benchmarkapps/Crankier/Agent.cs

@@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.SignalR.Crankier
         private AgentWorker CreateWorker()
         {
             var fileName = _executable;
-            var arguments = $"worker --agent {Process.GetCurrentProcess().Id}";
+            var arguments = $"worker --agent {Environment.ProcessId}";
             if (_workerWaitForDebugger)
             {
                 arguments += " --wait-for-debugger";

+ 1 - 1
src/SignalR/perf/benchmarkapps/Crankier/Worker.cs

@@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.SignalR.Crankier
         {
             _agentProcess = Process.GetProcessById(agentProcessId);
             _agent = new AgentSender(new StreamWriter(Console.OpenStandardOutput()));
-            _processId = Process.GetCurrentProcess().Id;
+            _processId = Environment.ProcessId;
             _clients = new ConcurrentBag<Client>();
             _sendStatusCts = new CancellationTokenSource();
         }

+ 1 - 1
src/SignalR/server/Core/src/Internal/HubGroupList.cs

@@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal
 
         public void RemoveDisconnectedConnection(string connectionId)
         {
-            var groupNames = _groups.Where(x => x.Value.Keys.Contains(connectionId)).Select(x => x.Key);
+            var groupNames = _groups.Where(x => x.Value.ContainsKey(connectionId)).Select(x => x.Key);
             foreach (var groupName in groupNames)
             {
                 Remove(connectionId, groupName);

+ 1 - 1
src/Tools/Microsoft.dotnet-openapi/src/DebugMode.cs

@@ -16,7 +16,7 @@ namespace Microsoft.DotNet.OpenApi
             {
                 args = args.Skip(1).ToArray();
 
-                Console.WriteLine("Waiting for debugger in pid: {0}", Process.GetCurrentProcess().Id);
+                Console.WriteLine("Waiting for debugger in pid: {0}", Environment.ProcessId);
                 while (!Debugger.IsAttached)
                 {
                     Thread.Sleep(TimeSpan.FromSeconds(3));

+ 4 - 0
src/Tools/Shared/CommandLine/DebugHelper.cs

@@ -20,7 +20,11 @@ namespace Microsoft.Extensions.Tools.Internal
             {
                 args = args.Skip(1).ToArray();
                 Console.WriteLine("Waiting for debugger to attach. Press ENTER to continue");
+#if NET6_0_OR_GREATER
+                Console.WriteLine($"Process ID: {Environment.ProcessId}");
+#else
                 Console.WriteLine($"Process ID: {Process.GetCurrentProcess().Id}");
+#endif
                 Console.ReadLine();
             }
         }