Skip to content

Commit 495d3b2

Browse files
authored
Add a test to verify NewtonsoftJsonInputFormatter disposes temporary buffer (#25919)
#22342 was fixed in a patch release, but we hadn't written a test for this at that time. This change adds a unit test to verify this. Fixes #22342
1 parent 50eb578 commit 495d3b2

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ public override async Task<InputFormatterResult> ReadRequestBodyAsync(
123123
throw new ArgumentNullException(nameof(encoding));
124124
}
125125

126-
var request = context.HttpContext.Request;
126+
var httpContext = context.HttpContext;
127+
var request = httpContext.Request;
127128

128129
var suppressInputFormatterBuffering = _options.SuppressInputFormatterBuffering;
129130

@@ -153,7 +154,7 @@ public override async Task<InputFormatterResult> ReadRequestBodyAsync(
153154

154155
readStream = new FileBufferingReadStream(request.Body, memoryThreshold);
155156
// Ensure the file buffer stream is always disposed at the end of a request.
156-
request.HttpContext.Response.RegisterForDispose(readStream);
157+
httpContext.Response.RegisterForDispose(readStream);
157158

158159
await readStream.DrainAsync(CancellationToken.None);
159160
readStream.Seek(0L, SeekOrigin.Begin);

src/Mvc/Mvc.NewtonsoftJson/test/NewtonsoftJsonInputFormatterTest.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Threading.Tasks;
1010
using Microsoft.AspNetCore.Http;
1111
using Microsoft.AspNetCore.Http.Features;
12+
using Microsoft.AspNetCore.WebUtilities;
1213
using Microsoft.Extensions.Logging;
1314
using Microsoft.Extensions.Logging.Abstractions;
1415
using Microsoft.Extensions.ObjectPool;
@@ -399,6 +400,39 @@ public async Task ReadAsync_DoesNotRethrowOverflowExceptions()
399400
Assert.Equal("The supplied value is invalid.", modelError.ErrorMessage);
400401
}
401402

403+
[Fact]
404+
public async Task ReadAsync_RegistersFileStreamForDisposal()
405+
{
406+
// Arrange
407+
var formatter = new NewtonsoftJsonInputFormatter(
408+
GetLogger(),
409+
_serializerSettings,
410+
ArrayPool<char>.Shared,
411+
_objectPoolProvider,
412+
new MvcOptions(),
413+
new MvcNewtonsoftJsonOptions());
414+
var httpContext = new Mock<HttpContext>();
415+
IDisposable registerForDispose = null;
416+
417+
var content = Encoding.UTF8.GetBytes("\"Hello world\"");
418+
httpContext.Setup(h => h.Request.Body).Returns(new NonSeekableReadStream(content, allowSyncReads: false));
419+
httpContext.Setup(h => h.Request.ContentType).Returns("application/json");
420+
httpContext.Setup(h => h.Response.RegisterForDispose(It.IsAny<IDisposable>()))
421+
.Callback((IDisposable disposable) => registerForDispose = disposable)
422+
.Verifiable();
423+
424+
var formatterContext = CreateInputFormatterContext(typeof(string), httpContext.Object);
425+
426+
// Act
427+
var result = await formatter.ReadAsync(formatterContext);
428+
429+
// Assert
430+
Assert.Equal("Hello world", result.Model);
431+
Assert.NotNull(registerForDispose);
432+
Assert.IsType<FileBufferingReadStream>(registerForDispose);
433+
httpContext.Verify();
434+
}
435+
402436
private class TestableJsonInputFormatter : NewtonsoftJsonInputFormatter
403437
{
404438
public TestableJsonInputFormatter(JsonSerializerSettings settings, ObjectPoolProvider objectPoolProvider)

0 commit comments

Comments
 (0)