[Fixes #5413] JsonOutputFormatter adds all closing brackets when exceptions are thrown

This commit is contained in:
Kiran Challa 2017-03-20 14:52:29 -07:00
parent b22326323a
commit c18f0780c1
4 changed files with 88 additions and 4 deletions

View File

@ -33,8 +33,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
/// <param name="options">The <see cref="IOptions{MvcJsonOptions}"/>.</param>
/// <param name="charPool">The <see cref="ArrayPool{Char}"/> for creating <see cref="T:char[]"/> buffers.</param>
public JsonResultExecutor(
IHttpResponseStreamWriterFactory writerFactory,
ILogger<JsonResultExecutor> logger,
IHttpResponseStreamWriterFactory writerFactory,
ILogger<JsonResultExecutor> logger,
IOptions<MvcJsonOptions> options,
ArrayPool<char> 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);

View File

@ -97,6 +97,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{
ArrayPool = _charPool,
CloseOutput = false,
AutoCompleteOnClose = false
};
return jsonWriter;

View File

@ -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<NotImplementedException>(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<MemoryStream>(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");
}
}
}
}
}

View File

@ -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<char>.Shared);
// Act
try
{
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext, Encoding.UTF8);
}
catch (JsonSerializationException serializerException)
{
var expectedException = Assert.IsType<NotImplementedException>(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");
}
}
}
}
}