diff --git a/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Internal/JsonResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Internal/JsonResultExecutor.cs
index 79c9ee851d..f64082e9a5 100644
--- a/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Internal/JsonResultExecutor.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Internal/JsonResultExecutor.cs
@@ -33,8 +33,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
/// The .
/// The for creating buffers.
public JsonResultExecutor(
- IHttpResponseStreamWriterFactory writerFactory,
- ILogger logger,
+ IHttpResponseStreamWriterFactory writerFactory,
+ ILogger logger,
IOptions options,
ArrayPool charPool)
{
@@ -124,6 +124,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
{
jsonWriter.ArrayPool = _charPool;
jsonWriter.CloseOutput = false;
+ jsonWriter.AutoCompleteOnClose = false;
var jsonSerializer = JsonSerializer.Create(serializerSettings);
jsonSerializer.Serialize(jsonWriter, result.Value);
diff --git a/src/Microsoft.AspNetCore.Mvc.Formatters.Json/JsonOutputFormatter.cs b/src/Microsoft.AspNetCore.Mvc.Formatters.Json/JsonOutputFormatter.cs
index 111a7df47f..98bbe2e0af 100644
--- a/src/Microsoft.AspNetCore.Mvc.Formatters.Json/JsonOutputFormatter.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Formatters.Json/JsonOutputFormatter.cs
@@ -97,6 +97,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{
ArrayPool = _charPool,
CloseOutput = false,
+ AutoCompleteOnClose = false
};
return jsonWriter;
diff --git a/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/Internal/JsonResultExecutorTest.cs b/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/Internal/JsonResultExecutorTest.cs
index c48eaa4856..aa32faad36 100644
--- a/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/Internal/JsonResultExecutorTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/Internal/JsonResultExecutorTest.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.Text;
@@ -156,6 +157,31 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
Assert.Equal("application/json; charset=utf-8", context.HttpContext.Response.ContentType);
}
+ [Fact]
+ public async Task ExecuteAsync_ErrorDuringSerialization_DoesNotCloseTheBrackets()
+ {
+ // Arrange
+ var expected = Encoding.UTF8.GetBytes("{\"name\":\"Robert\"");
+ var context = GetActionContext();
+ var result = new JsonResult(new ModelWithSerializationError());
+ var executor = CreateExcutor();
+
+ // Act
+ try
+ {
+ await executor.ExecuteAsync(context, result);
+ }
+ catch (JsonSerializationException serializerException)
+ {
+ var expectedException = Assert.IsType(serializerException.InnerException);
+ Assert.Equal("Property Age has not been implemented", expectedException.Message);
+ }
+
+ // Assert
+ var written = GetWrittenBytes(context.HttpContext);
+ Assert.Equal(expected, written);
+ }
+
private static JsonResultExecutor CreateExcutor()
{
return new JsonResultExecutor(
@@ -188,5 +214,17 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
context.Response.Body.Seek(0, SeekOrigin.Begin);
return Assert.IsType(context.Response.Body).ToArray();
}
+
+ private class ModelWithSerializationError
+ {
+ public string Name { get; } = "Robert";
+ public int Age
+ {
+ get
+ {
+ throw new NotImplementedException($"Property {nameof(Age)} has not been implemented");
+ }
+ }
+ }
}
}
diff --git a/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs b/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs
index 84075cd15a..b71ed5a3a2 100644
--- a/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs
@@ -313,7 +313,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{ "This is a test 激光這兩個字是甚麼意思 string written using shift_jis", "shift_jis", false },
#elif NETCOREAPP2_0
#else
-#error target frameworks needs to be updated.
+#error target frameworks needs to be updated.
#endif
{ "This is a test æøå string written using iso-8859-1", "iso-8859-1", false },
};
@@ -327,7 +327,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
}
#elif NETCOREAPP2_0
#else
-#error target frameworks needs to be updated.
+#error target frameworks needs to be updated.
#endif
return data;
@@ -369,6 +369,38 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
Assert.Equal(expectedData, actualData);
}
+ [Fact]
+ public async Task ErrorDuringSerialization_DoesNotCloseTheBrackets()
+ {
+ // Arrange
+ var expectedOutput = "{\"name\":\"Robert\"";
+ var outputFormatterContext = GetOutputFormatterContext(
+ new ModelWithSerializationError(),
+ typeof(ModelWithSerializationError));
+ var serializerSettings = JsonSerializerSettingsProvider.CreateSerializerSettings();
+ var jsonFormatter = new JsonOutputFormatter(serializerSettings, ArrayPool.Shared);
+
+ // Act
+ try
+ {
+ await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext, Encoding.UTF8);
+ }
+ catch (JsonSerializationException serializerException)
+ {
+ var expectedException = Assert.IsType(serializerException.InnerException);
+ Assert.Equal("Property Age has not been implemented", expectedException.Message);
+ }
+
+ // Assert
+ var body = outputFormatterContext.HttpContext.Response.Body;
+
+ Assert.NotNull(body);
+ body.Position = 0;
+
+ var content = new StreamReader(body, Encoding.UTF8).ReadToEnd();
+ Assert.Equal(expectedOutput, content);
+ }
+
private static Encoding CreateOrGetSupportedEncoding(
JsonOutputFormatter formatter,
string encodingAsString,
@@ -467,5 +499,17 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
public string FullName { get; set; }
}
+
+ private class ModelWithSerializationError
+ {
+ public string Name { get; } = "Robert";
+ public int Age
+ {
+ get
+ {
+ throw new NotImplementedException($"Property {nameof(Age)} has not been implemented");
+ }
+ }
+ }
}
}
\ No newline at end of file