diff --git a/src/Hosting/TestHost/src/AsyncStreamWrapper.cs b/src/Hosting/TestHost/src/AsyncStreamWrapper.cs index 4766f8fcf1..705d5a7a0e 100644 --- a/src/Hosting/TestHost/src/AsyncStreamWrapper.cs +++ b/src/Hosting/TestHost/src/AsyncStreamWrapper.cs @@ -116,17 +116,18 @@ namespace Microsoft.AspNetCore.TestHost public override void Close() { - _inner.Close(); + // Don't dispose the inner stream, we don't want to impact the client stream } protected override void Dispose(bool disposing) { - _inner.Dispose(); + // Don't dispose the inner stream, we don't want to impact the client stream } public override ValueTask DisposeAsync() { - return _inner.DisposeAsync(); + // Don't dispose the inner stream, we don't want to impact the client stream + return default; } } } diff --git a/src/Hosting/TestHost/test/TestServerTests.cs b/src/Hosting/TestHost/test/TestServerTests.cs index cc789962c7..2eb474b496 100644 --- a/src/Hosting/TestHost/test/TestServerTests.cs +++ b/src/Hosting/TestHost/test/TestServerTests.cs @@ -3,8 +3,10 @@ using System; using System.Diagnostics; +using System.IO; using System.Net; using System.Net.Http; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; @@ -18,6 +20,7 @@ using Microsoft.Extensions.DiagnosticAdapter; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Net.Http.Headers; +using Moq; using Xunit; namespace Microsoft.AspNetCore.TestHost @@ -191,6 +194,28 @@ namespace Microsoft.AspNetCore.TestHost Assert.Equal("RequestServices:True", result); } + [Fact] + public async Task DispoingTheRequestBodyDoesNotDisposeClientStreams() + { + var builder = new WebHostBuilder().Configure(app => + { + app.Run(async context => + { + using (var sr = new StreamReader(context.Request.Body)) + { + await context.Response.WriteAsync(await sr.ReadToEndAsync()); + } + }); + }); + var server = new TestServer(builder); + + var stream = new ThrowOnDisposeStream(); + stream.Write(Encoding.ASCII.GetBytes("Hello World")); + var response = await server.CreateClient().PostAsync("/", new StreamContent(stream)); + Assert.True(response.IsSuccessStatusCode); + Assert.Equal("Hello World", await response.Content.ReadAsStringAsync()); + } + public class CustomContainerStartup { public IServiceProvider Services; @@ -662,6 +687,19 @@ namespace Microsoft.AspNetCore.TestHost Assert.Equal("otherhost:5678", responseBody); } + private class ThrowOnDisposeStream : MemoryStream + { + protected override void Dispose(bool disposing) + { + throw new InvalidOperationException("Dispose should not happen!"); + } + + public override ValueTask DisposeAsync() + { + throw new InvalidOperationException("DisposeAsync should not happen!"); + } + } + public class TestDiagnosticListener { public class OnBeginRequestEventData