* Debug log exceptions in JsonInput deserializing

This commit is contained in:
ryanbrandenburg 2015-11-23 16:42:36 -08:00
parent d22d6793ba
commit 91e837d465
13 changed files with 138 additions and 44 deletions

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel; using Microsoft.Extensions.OptionsModel;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -10,18 +11,23 @@ namespace Microsoft.AspNet.Mvc.Formatters.Json.Internal
{ {
public class MvcJsonMvcOptionsSetup : ConfigureOptions<MvcOptions> public class MvcJsonMvcOptionsSetup : ConfigureOptions<MvcOptions>
{ {
public MvcJsonMvcOptionsSetup(IOptions<MvcJsonOptions> jsonOptions) public MvcJsonMvcOptionsSetup(ILoggerFactory loggerFactory, IOptions<MvcJsonOptions> jsonOptions)
: base((_) => ConfigureMvc(_, jsonOptions.Value.SerializerSettings)) : base((_) => ConfigureMvc(_, jsonOptions.Value.SerializerSettings, loggerFactory))
{ {
} }
public static void ConfigureMvc(MvcOptions options, JsonSerializerSettings serializerSettings) public static void ConfigureMvc(
MvcOptions options,
JsonSerializerSettings serializerSettings,
ILoggerFactory loggerFactory)
{ {
var jsonInputLogger = loggerFactory.CreateLogger<JsonInputFormatter>();
var jsonInputPatchLogger = loggerFactory.CreateLogger<JsonPatchInputFormatter>();
options.OutputFormatters.Add(new JsonOutputFormatter(serializerSettings)); options.OutputFormatters.Add(new JsonOutputFormatter(serializerSettings));
options.InputFormatters.Add(new JsonInputFormatter(jsonInputLogger, serializerSettings));
options.InputFormatters.Add(new JsonInputFormatter(serializerSettings)); options.InputFormatters.Add(new JsonPatchInputFormatter(jsonInputPatchLogger, serializerSettings));
options.InputFormatters.Add(new JsonPatchInputFormatter(serializerSettings));
options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("application/json")); options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("application/json"));
options.ValidationExcludeFilters.Add(typeof(JToken)); options.ValidationExcludeFilters.Add(typeof(JToken));

View File

@ -2,12 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.IO;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Infrastructure; using Microsoft.AspNet.Mvc.Formatters.Json.Logging;
using Microsoft.AspNet.Mvc.Internal; using Microsoft.AspNet.Mvc.Internal;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Microsoft.AspNet.Mvc.Formatters namespace Microsoft.AspNet.Mvc.Formatters
@ -15,19 +14,27 @@ namespace Microsoft.AspNet.Mvc.Formatters
public class JsonInputFormatter : InputFormatter public class JsonInputFormatter : InputFormatter
{ {
private JsonSerializerSettings _serializerSettings; private JsonSerializerSettings _serializerSettings;
private ILogger _logger;
public JsonInputFormatter()
: this(SerializerSettingsProvider.CreateSerializerSettings()) public JsonInputFormatter(ILogger logger)
: this(logger, SerializerSettingsProvider.CreateSerializerSettings())
{ {
} }
public JsonInputFormatter(JsonSerializerSettings serializerSettings) public JsonInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings)
{ {
if (serializerSettings == null) if (serializerSettings == null)
{ {
throw new ArgumentNullException(nameof(serializerSettings)); throw new ArgumentNullException(nameof(serializerSettings));
} }
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
_logger = logger;
_serializerSettings = serializerSettings; _serializerSettings = serializerSettings;
SupportedEncodings.Add(UTF8EncodingWithoutBOM); SupportedEncodings.Add(UTF8EncodingWithoutBOM);
@ -107,6 +114,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
var metadata = GetPathMetadata(context.Metadata, eventArgs.ErrorContext.Path); var metadata = GetPathMetadata(context.Metadata, eventArgs.ErrorContext.Path);
context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error, metadata); context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error, metadata);
_logger.JsonInputException(eventArgs.ErrorContext.Error);
// Error must always be marked as handled // Error must always be marked as handled
// Failure to do so can cause the exception to be rethrown at every recursive level and // Failure to do so can cause the exception to be rethrown at every recursive level and
// overflow the stack for x64 CLR processes // overflow the stack for x64 CLR processes

View File

@ -6,19 +6,20 @@ using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.JsonPatch; using Microsoft.AspNet.JsonPatch;
using Microsoft.AspNet.Mvc.Internal; using Microsoft.AspNet.Mvc.Internal;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Microsoft.AspNet.Mvc.Formatters namespace Microsoft.AspNet.Mvc.Formatters
{ {
public class JsonPatchInputFormatter : JsonInputFormatter public class JsonPatchInputFormatter : JsonInputFormatter
{ {
public JsonPatchInputFormatter() public JsonPatchInputFormatter(ILogger logger)
: this(SerializerSettingsProvider.CreateSerializerSettings()) : this(logger, SerializerSettingsProvider.CreateSerializerSettings())
{ {
} }
public JsonPatchInputFormatter(JsonSerializerSettings serializerSettings) public JsonPatchInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings)
: base(serializerSettings) : base(logger, serializerSettings)
{ {
// Clear all values and only include json-patch+json value. // Clear all values and only include json-patch+json value.
SupportedMediaTypes.Clear(); SupportedMediaTypes.Clear();

View File

@ -0,0 +1,23 @@
using System;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc.Formatters.Json.Logging
{
internal static class JsonInputFormatterLoggerExtensions
{
private static readonly Action<ILogger, string, Exception> _jsonInputFormatterCrashed;
static JsonInputFormatterLoggerExtensions()
{
_jsonInputFormatterCrashed = LoggerMessage.Define<string>(
LogLevel.Verbose,
1,
"JSON input formatter threw an exception.");
}
public static void JsonInputException(this ILogger logger, Exception exception)
{
_jsonInputFormatterCrashed(logger, exception.ToString(), exception);
}
}
}

View File

@ -9,6 +9,8 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Moq; using Moq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
@ -33,7 +35,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentType, bool expectedCanRead) public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentType, bool expectedCanRead)
{ {
// Arrange // Arrange
var formatter = new JsonInputFormatter(); var loggerMock = GetLogger();
var formatter = new JsonInputFormatter(loggerMock);
var contentBytes = Encoding.UTF8.GetBytes("content"); var contentBytes = Encoding.UTF8.GetBytes("content");
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType); var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
@ -57,7 +61,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
public void DefaultMediaType_ReturnsApplicationJson() public void DefaultMediaType_ReturnsApplicationJson()
{ {
// Arrange // Arrange
var formatter = new JsonInputFormatter(); var loggerMock = GetLogger();
var formatter = new JsonInputFormatter(loggerMock);
// Act // Act
var mediaType = formatter.SupportedMediaTypes[0]; var mediaType = formatter.SupportedMediaTypes[0];
@ -82,7 +87,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
public async Task JsonFormatterReadsSimpleTypes(string content, Type type, object expected) public async Task JsonFormatterReadsSimpleTypes(string content, Type type, object expected)
{ {
// Arrange // Arrange
var formatter = new JsonInputFormatter(); var logger = GetLogger();
var formatter = new JsonInputFormatter(logger);
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
var httpContext = GetHttpContext(contentBytes); var httpContext = GetHttpContext(contentBytes);
@ -108,7 +114,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
{ {
// Arrange // Arrange
var content = "{name: 'Person Name', Age: '30'}"; var content = "{name: 'Person Name', Age: '30'}";
var formatter = new JsonInputFormatter(); var logger = GetLogger();
var formatter = new JsonInputFormatter(logger);
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
var httpContext = GetHttpContext(contentBytes); var httpContext = GetHttpContext(contentBytes);
@ -136,7 +143,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
{ {
// Arrange // Arrange
var content = "{name: 'Person Name', Age: 'not-an-age'}"; var content = "{name: 'Person Name', Age: 'not-an-age'}";
var formatter = new JsonInputFormatter(); var logger = GetLogger();
var formatter = new JsonInputFormatter(logger);
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
var modelState = new ModelStateDictionary(); var modelState = new ModelStateDictionary();
@ -165,7 +173,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
{ {
// Arrange // Arrange
var content = "[0, 23, 300]"; var content = "[0, 23, 300]";
var formatter = new JsonInputFormatter(); var logger = GetLogger();
var formatter = new JsonInputFormatter(logger);
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
var modelState = new ModelStateDictionary(); var modelState = new ModelStateDictionary();
@ -193,7 +202,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
{ {
// Arrange // Arrange
var content = "[{name: 'Name One', Age: 30}, {name: 'Name Two', Small: 300}]"; var content = "[{name: 'Name One', Age: 30}, {name: 'Name Two', Small: 300}]";
var formatter = new JsonInputFormatter(); var logger = GetLogger();
var formatter = new JsonInputFormatter(logger);
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
var modelState = new ModelStateDictionary(); var modelState = new ModelStateDictionary();
@ -222,7 +232,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
{ {
// Arrange // Arrange
var content = "{name: 'Person Name', Age: 'not-an-age'}"; var content = "{name: 'Person Name', Age: 'not-an-age'}";
var formatter = new JsonInputFormatter(); var logger = GetLogger();
var formatter = new JsonInputFormatter(logger);
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
var modelState = new ModelStateDictionary(); var modelState = new ModelStateDictionary();
@ -254,8 +265,10 @@ namespace Microsoft.AspNet.Mvc.Formatters
public void Creates_SerializerSettings_ByDefault() public void Creates_SerializerSettings_ByDefault()
{ {
// Arrange // Arrange
var logger = GetLogger();
// Act // Act
var jsonFormatter = new JsonInputFormatter(); var jsonFormatter = new JsonInputFormatter(logger);
// Assert // Assert
Assert.NotNull(jsonFormatter.SerializerSettings); Assert.NotNull(jsonFormatter.SerializerSettings);
@ -265,9 +278,11 @@ namespace Microsoft.AspNet.Mvc.Formatters
public void Constructor_UsesSerializerSettings() public void Constructor_UsesSerializerSettings()
{ {
// Arrange // Arrange
var logger = GetLogger();
// Act // Act
var serializerSettings = new JsonSerializerSettings(); var serializerSettings = new JsonSerializerSettings();
var jsonFormatter = new JsonInputFormatter(serializerSettings); var jsonFormatter = new JsonInputFormatter(logger, serializerSettings);
// Assert // Assert
Assert.Same(serializerSettings, jsonFormatter.SerializerSettings); Assert.Same(serializerSettings, jsonFormatter.SerializerSettings);
@ -279,8 +294,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Arrange // Arrange
// missing password property here // missing password property here
var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}"); var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}");
var logger = GetLogger();
var jsonFormatter = new JsonInputFormatter(); var jsonFormatter = new JsonInputFormatter(logger);
// by default we ignore missing members, so here explicitly changing it // by default we ignore missing members, so here explicitly changing it
jsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error; jsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
@ -312,8 +327,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Arrange // Arrange
// missing password property here // missing password property here
var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}"); var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}");
var logger = GetLogger();
var jsonFormatter = new JsonInputFormatter(); var jsonFormatter = new JsonInputFormatter(logger);
// by default we ignore missing members, so here explicitly changing it // by default we ignore missing members, so here explicitly changing it
jsonFormatter.SerializerSettings = new JsonSerializerSettings() jsonFormatter.SerializerSettings = new JsonSerializerSettings()
{ {
@ -342,6 +357,11 @@ namespace Microsoft.AspNet.Mvc.Formatters
Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage); Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage);
} }
private static ILogger GetLogger()
{
return NullLogger.Instance;
}
private static HttpContext GetHttpContext( private static HttpContext GetHttpContext(
byte[] contentBytes, byte[] contentBytes,
string contentType = "application/json") string contentType = "application/json")

View File

@ -12,6 +12,8 @@ using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.Internal; using Microsoft.AspNet.Mvc.Internal;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Testing; using Microsoft.AspNet.Testing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using Moq; using Moq;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -40,7 +42,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Arrange // Arrange
// Act // Act
var serializerSettings = new JsonSerializerSettings(); var serializerSettings = new JsonSerializerSettings();
var jsonFormatter = new JsonInputFormatter(serializerSettings); var logger = GetLogger();
var jsonFormatter = new JsonInputFormatter(logger, serializerSettings);
// Assert // Assert
Assert.Same(serializerSettings, jsonFormatter.SerializerSettings); Assert.Same(serializerSettings, jsonFormatter.SerializerSettings);
@ -290,6 +293,11 @@ namespace Microsoft.AspNet.Mvc.Formatters
return encoding; return encoding;
} }
private static ILogger GetLogger()
{
return NullLogger.Instance;
}
private static OutputFormatterWriteContext GetOutputFormatterContext( private static OutputFormatterWriteContext GetOutputFormatterContext(
object outputValue, object outputValue,
Type outputType, Type outputType,

View File

@ -8,6 +8,8 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.JsonPatch; using Microsoft.AspNet.JsonPatch;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Moq; using Moq;
using Xunit; using Xunit;
@ -19,7 +21,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
public async Task JsonPatchInputFormatter_ReadsOneOperation_Successfully() public async Task JsonPatchInputFormatter_ReadsOneOperation_Successfully()
{ {
// Arrange // Arrange
var formatter = new JsonPatchInputFormatter(); var logger = GetLogger();
var formatter = new JsonPatchInputFormatter(logger);
var content = "[{\"op\":\"add\",\"path\":\"Customer/Name\",\"value\":\"John\"}]"; var content = "[{\"op\":\"add\",\"path\":\"Customer/Name\",\"value\":\"John\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
@ -49,7 +52,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
public async Task JsonPatchInputFormatter_ReadsMultipleOperations_Successfully() public async Task JsonPatchInputFormatter_ReadsMultipleOperations_Successfully()
{ {
// Arrange // Arrange
var formatter = new JsonPatchInputFormatter(); var logger = GetLogger();
var formatter = new JsonPatchInputFormatter(logger);
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}," + var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}," +
"{\"op\": \"remove\", \"path\" : \"Customer/Name\"}]"; "{\"op\": \"remove\", \"path\" : \"Customer/Name\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
@ -86,7 +90,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
public void CanRead_ReturnsTrueOnlyForJsonPatchContentType(string requestContentType, bool expectedCanRead) public void CanRead_ReturnsTrueOnlyForJsonPatchContentType(string requestContentType, bool expectedCanRead)
{ {
// Arrange // Arrange
var formatter = new JsonPatchInputFormatter(); var logger = GetLogger();
var formatter = new JsonPatchInputFormatter(logger);
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]"; var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
@ -114,7 +119,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
public void CanRead_ReturnsFalse_NonJsonPatchContentType(Type modelType) public void CanRead_ReturnsFalse_NonJsonPatchContentType(Type modelType)
{ {
// Arrange // Arrange
var formatter = new JsonPatchInputFormatter(); var logger = GetLogger();
var formatter = new JsonPatchInputFormatter(logger);
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]"; var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
@ -143,7 +149,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
var exceptionMessage = "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type " + var exceptionMessage = "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type " +
$"'{typeof(Customer).FullName}' because the type requires a JSON object "; $"'{typeof(Customer).FullName}' because the type requires a JSON object ";
var formatter = new JsonPatchInputFormatter(); var logger = GetLogger();
var formatter = new JsonPatchInputFormatter(logger);
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]"; var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
@ -166,6 +173,11 @@ namespace Microsoft.AspNet.Mvc.Formatters
Assert.Contains(exceptionMessage, modelState[""].Errors[0].Exception.Message); Assert.Contains(exceptionMessage, modelState[""].Errors[0].Exception.Message);
} }
private static ILogger GetLogger()
{
return NullLogger.Instance;
}
private static HttpContext GetHttpContext( private static HttpContext GetHttpContext(
byte[] contentBytes, byte[] contentBytes,
string contentType = "application/json-patch+json") string contentType = "application/json-patch+json")

View File

@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ModelBinding.Validation; using Microsoft.AspNet.Mvc.ModelBinding.Validation;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel; using Microsoft.Extensions.OptionsModel;
namespace Microsoft.AspNet.Mvc.IntegrationTests namespace Microsoft.AspNet.Mvc.IntegrationTests
@ -70,6 +71,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var serviceCollection = new ServiceCollection(); var serviceCollection = new ServiceCollection();
serviceCollection.AddMvc(); serviceCollection.AddMvc();
serviceCollection.AddTransient<ILoggerFactory, LoggerFactory>();
if (updateOptions != null) if (updateOptions != null)
{ {

View File

@ -5,6 +5,7 @@ using Microsoft.AspNet.Mvc.DataAnnotations.Internal;
using Microsoft.AspNet.Mvc.Formatters.Json.Internal; using Microsoft.AspNet.Mvc.Formatters.Json.Internal;
using Microsoft.AspNet.Mvc.Internal; using Microsoft.AspNet.Mvc.Internal;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel; using Microsoft.Extensions.OptionsModel;
namespace Microsoft.AspNet.Mvc.IntegrationTests namespace Microsoft.AspNet.Mvc.IntegrationTests
@ -19,7 +20,11 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
MvcDataAnnotationsMvcOptionsSetup.ConfigureMvc( MvcDataAnnotationsMvcOptionsSetup.ConfigureMvc(
Value, Value,
collection.BuildServiceProvider()); collection.BuildServiceProvider());
MvcJsonMvcOptionsSetup.ConfigureMvc(Value, SerializerSettingsProvider.CreateSerializerSettings());
var loggerFactory = new LoggerFactory();
var serializerSettings = SerializerSettingsProvider.CreateSerializerSettings();
MvcJsonMvcOptionsSetup.ConfigureMvc(Value, serializerSettings, loggerFactory);
} }
public MvcOptions Value { get; } public MvcOptions Value { get; }

View File

@ -18,6 +18,7 @@ using Microsoft.Extensions.OptionsModel;
using Moq; using Moq;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Xunit; using Xunit;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
@ -191,7 +192,10 @@ namespace Microsoft.AspNet.Mvc
public void Setup_JsonFormattersUseSerializerSettings() public void Setup_JsonFormattersUseSerializerSettings()
{ {
// Arrange // Arrange
var services = GetServiceProvider(); var services = GetServiceProvider(s =>
{
s.AddTransient<ILoggerFactory, LoggerFactory>();
});
// Act // Act
var options = services.GetRequiredService<IOptions<MvcOptions>>().Value; var options = services.GetRequiredService<IOptions<MvcOptions>>().Value;
@ -222,7 +226,7 @@ namespace Microsoft.AspNet.Mvc
{ {
var serviceCollection = new ServiceCollection(); var serviceCollection = new ServiceCollection();
serviceCollection.AddMvc(); serviceCollection.AddMvc();
serviceCollection.AddTransient<ILoggerFactory, LoggerFactory>();
if (action != null) if (action != null)
{ {
action(serviceCollection); action(serviceCollection);

View File

@ -2,9 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Formatters; using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace ApiExplorerWebSite namespace ApiExplorerWebSite
{ {
@ -13,6 +13,7 @@ namespace ApiExplorerWebSite
// Set up application services // Set up application services
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddTransient<ILoggerFactory, LoggerFactory>();
services.AddMvc(options => services.AddMvc(options =>
{ {
options.Filters.AddService(typeof(ApiExplorerDataFilter)); options.Filters.AddService(typeof(ApiExplorerDataFilter));

View File

@ -5,6 +5,8 @@ using System;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.Formatters; using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
@ -61,8 +63,9 @@ namespace BasicWebSite
// Instead remove and add new formatters which only effects the controllers this // Instead remove and add new formatters which only effects the controllers this
// attribute is decorated on. // attribute is decorated on.
context.InputFormatters.RemoveType<JsonInputFormatter>(); context.InputFormatters.RemoveType<JsonInputFormatter>();
context.InputFormatters.Add(new JsonInputFormatter(_serializerSettings)); var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<JsonInputFormatter>();
context.InputFormatters.Add(new JsonInputFormatter(logger ,_serializerSettings));
} }
public void OnResultExecuted(ResultExecutedContext context) public void OnResultExecuted(ResultExecutedContext context)

View File

@ -16,7 +16,7 @@ namespace BasicWebSite
{ {
options.Conventions.Add(new ApplicationDescription("This is a basic website.")); options.Conventions.Add(new ApplicationDescription("This is a basic website."));
}); });
services.AddLogging();
services.AddSingleton<IActionDescriptorProvider, ActionDescriptorCreationCounter>(); services.AddSingleton<IActionDescriptorProvider, ActionDescriptorCreationCounter>();
} }