From 91e837d465888fb70327e3a4be15ed9ecc18cb83 Mon Sep 17 00:00:00 2001 From: ryanbrandenburg Date: Mon, 23 Nov 2015 16:42:36 -0800 Subject: [PATCH] * Debug log exceptions in JsonInput deserializing --- .../Internal/MvcJsonMvcOptionsSetup.cs | 20 +++++--- .../JsonInputFormatter.cs | 21 +++++--- .../JsonPatchInputFormatter.cs | 9 ++-- .../JsonInputFormatterLoggerExtensions.cs | 23 +++++++++ .../JsonInputFormatterTest.cs | 48 +++++++++++++------ .../JsonOutputFormatterTests.cs | 10 +++- .../JsonPatchInputFormatterTest.cs | 22 +++++++-- .../ModelBindingTestHelper.cs | 2 + .../TestMvcOptions.cs | 7 ++- .../MvcOptionsSetupTest.cs | 8 +++- test/WebSites/ApiExplorerWebSite/Startup.cs | 3 +- .../SpecificFormattersController.cs | 7 ++- test/WebSites/BasicWebSite/Startup.cs | 2 +- 13 files changed, 138 insertions(+), 44 deletions(-) create mode 100644 src/Microsoft.AspNet.Mvc.Formatters.Json/Logging/JsonInputFormatterLoggerExtensions.cs diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Json/Internal/MvcJsonMvcOptionsSetup.cs b/src/Microsoft.AspNet.Mvc.Formatters.Json/Internal/MvcJsonMvcOptionsSetup.cs index 75a72b8b12..2241518322 100644 --- a/src/Microsoft.AspNet.Mvc.Formatters.Json/Internal/MvcJsonMvcOptionsSetup.cs +++ b/src/Microsoft.AspNet.Mvc.Formatters.Json/Internal/MvcJsonMvcOptionsSetup.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 Microsoft.Extensions.Logging; using Microsoft.Extensions.OptionsModel; using Microsoft.Net.Http.Headers; using Newtonsoft.Json; @@ -10,18 +11,23 @@ namespace Microsoft.AspNet.Mvc.Formatters.Json.Internal { public class MvcJsonMvcOptionsSetup : ConfigureOptions { - public MvcJsonMvcOptionsSetup(IOptions jsonOptions) - : base((_) => ConfigureMvc(_, jsonOptions.Value.SerializerSettings)) + public MvcJsonMvcOptionsSetup(ILoggerFactory loggerFactory, IOptions jsonOptions) + : base((_) => ConfigureMvc(_, jsonOptions.Value.SerializerSettings, loggerFactory)) { } - public static void ConfigureMvc(MvcOptions options, JsonSerializerSettings serializerSettings) + public static void ConfigureMvc( + MvcOptions options, + JsonSerializerSettings serializerSettings, + ILoggerFactory loggerFactory) { - options.OutputFormatters.Add(new JsonOutputFormatter(serializerSettings)); - - options.InputFormatters.Add(new JsonInputFormatter(serializerSettings)); - options.InputFormatters.Add(new JsonPatchInputFormatter(serializerSettings)); + var jsonInputLogger = loggerFactory.CreateLogger(); + var jsonInputPatchLogger = loggerFactory.CreateLogger(); + options.OutputFormatters.Add(new JsonOutputFormatter(serializerSettings)); + options.InputFormatters.Add(new JsonInputFormatter(jsonInputLogger, serializerSettings)); + options.InputFormatters.Add(new JsonPatchInputFormatter(jsonInputPatchLogger, serializerSettings)); + options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("application/json")); options.ValidationExcludeFilters.Add(typeof(JToken)); diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonInputFormatter.cs b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonInputFormatter.cs index 7783835f0f..903ffbaf98 100644 --- a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonInputFormatter.cs +++ b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonInputFormatter.cs @@ -2,12 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.IO; -using System.Text; 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.ModelBinding; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace Microsoft.AspNet.Mvc.Formatters @@ -15,19 +14,27 @@ namespace Microsoft.AspNet.Mvc.Formatters public class JsonInputFormatter : InputFormatter { 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) { throw new ArgumentNullException(nameof(serializerSettings)); } + if (logger == null) + { + throw new ArgumentNullException(nameof(logger)); + } + + _logger = logger; _serializerSettings = serializerSettings; SupportedEncodings.Add(UTF8EncodingWithoutBOM); @@ -107,6 +114,8 @@ public override Task ReadRequestBodyAsync(InputFormatterCo var metadata = GetPathMetadata(context.Metadata, eventArgs.ErrorContext.Path); context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error, metadata); + _logger.JsonInputException(eventArgs.ErrorContext.Error); + // Error must always be marked as handled // Failure to do so can cause the exception to be rethrown at every recursive level and // overflow the stack for x64 CLR processes diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonPatchInputFormatter.cs b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonPatchInputFormatter.cs index dd54998e60..61df53c7cd 100644 --- a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonPatchInputFormatter.cs +++ b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonPatchInputFormatter.cs @@ -6,19 +6,20 @@ using System.Threading.Tasks; using Microsoft.AspNet.JsonPatch; using Microsoft.AspNet.Mvc.Internal; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace Microsoft.AspNet.Mvc.Formatters { public class JsonPatchInputFormatter : JsonInputFormatter { - public JsonPatchInputFormatter() - : this(SerializerSettingsProvider.CreateSerializerSettings()) + public JsonPatchInputFormatter(ILogger logger) + : this(logger, SerializerSettingsProvider.CreateSerializerSettings()) { } - public JsonPatchInputFormatter(JsonSerializerSettings serializerSettings) - : base(serializerSettings) + public JsonPatchInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings) + : base(logger, serializerSettings) { // Clear all values and only include json-patch+json value. SupportedMediaTypes.Clear(); diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Json/Logging/JsonInputFormatterLoggerExtensions.cs b/src/Microsoft.AspNet.Mvc.Formatters.Json/Logging/JsonInputFormatterLoggerExtensions.cs new file mode 100644 index 0000000000..f7125030b7 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Formatters.Json/Logging/JsonInputFormatterLoggerExtensions.cs @@ -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 _jsonInputFormatterCrashed; + + static JsonInputFormatterLoggerExtensions() + { + _jsonInputFormatterCrashed = LoggerMessage.Define( + LogLevel.Verbose, + 1, + "JSON input formatter threw an exception."); + } + + public static void JsonInputException(this ILogger logger, Exception exception) + { + _jsonInputFormatterCrashed(logger, exception.ToString(), exception); + } + } +} diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs index 7107b8791a..c2418f7ec1 100644 --- a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs +++ b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs @@ -9,6 +9,8 @@ using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; using Moq; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -33,7 +35,9 @@ public class JsonInputFormatterTest public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentType, bool expectedCanRead) { // Arrange - var formatter = new JsonInputFormatter(); + var loggerMock = GetLogger(); + + var formatter = new JsonInputFormatter(loggerMock); var contentBytes = Encoding.UTF8.GetBytes("content"); var httpContext = GetHttpContext(contentBytes, contentType: requestContentType); @@ -57,7 +61,8 @@ public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentT public void DefaultMediaType_ReturnsApplicationJson() { // Arrange - var formatter = new JsonInputFormatter(); + var loggerMock = GetLogger(); + var formatter = new JsonInputFormatter(loggerMock); // Act var mediaType = formatter.SupportedMediaTypes[0]; @@ -82,7 +87,8 @@ public static IEnumerable JsonFormatterReadSimpleTypesData public async Task JsonFormatterReadsSimpleTypes(string content, Type type, object expected) { // Arrange - var formatter = new JsonInputFormatter(); + var logger = GetLogger(); + var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = GetHttpContext(contentBytes); @@ -108,7 +114,8 @@ public async Task JsonFormatterReadsComplexTypes() { // Arrange 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 httpContext = GetHttpContext(contentBytes); @@ -136,7 +143,8 @@ public async Task ReadAsync_AddsModelValidationErrorsToModelState() { // Arrange 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 modelState = new ModelStateDictionary(); @@ -165,7 +173,8 @@ public async Task ReadAsync_InvalidArray_AddsOverflowErrorsToModelState() { // Arrange var content = "[0, 23, 300]"; - var formatter = new JsonInputFormatter(); + var logger = GetLogger(); + var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); @@ -193,7 +202,8 @@ public async Task ReadAsync_InvalidComplexArray_AddsOverflowErrorsToModelState() { // Arrange 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 modelState = new ModelStateDictionary(); @@ -222,7 +232,8 @@ public async Task ReadAsync_UsesTryAddModelValidationErrorsToModelState() { // Arrange 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 modelState = new ModelStateDictionary(); @@ -254,8 +265,10 @@ public async Task ReadAsync_UsesTryAddModelValidationErrorsToModelState() public void Creates_SerializerSettings_ByDefault() { // Arrange + var logger = GetLogger(); + // Act - var jsonFormatter = new JsonInputFormatter(); + var jsonFormatter = new JsonInputFormatter(logger); // Assert Assert.NotNull(jsonFormatter.SerializerSettings); @@ -265,9 +278,11 @@ public void Creates_SerializerSettings_ByDefault() public void Constructor_UsesSerializerSettings() { // Arrange + var logger = GetLogger(); + // Act var serializerSettings = new JsonSerializerSettings(); - var jsonFormatter = new JsonInputFormatter(serializerSettings); + var jsonFormatter = new JsonInputFormatter(logger, serializerSettings); // Assert Assert.Same(serializerSettings, jsonFormatter.SerializerSettings); @@ -279,8 +294,8 @@ public async Task ChangesTo_DefaultSerializerSettings_TakesEffect() // Arrange // missing password property here var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}"); - - var jsonFormatter = new JsonInputFormatter(); + var logger = GetLogger(); + var jsonFormatter = new JsonInputFormatter(logger); // by default we ignore missing members, so here explicitly changing it jsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error; @@ -312,8 +327,8 @@ public async Task CustomSerializerSettingsObject_TakesEffect() // Arrange // missing password property here var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}"); - - var jsonFormatter = new JsonInputFormatter(); + var logger = GetLogger(); + var jsonFormatter = new JsonInputFormatter(logger); // by default we ignore missing members, so here explicitly changing it jsonFormatter.SerializerSettings = new JsonSerializerSettings() { @@ -342,6 +357,11 @@ public async Task CustomSerializerSettingsObject_TakesEffect() Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage); } + private static ILogger GetLogger() + { + return NullLogger.Instance; + } + private static HttpContext GetHttpContext( byte[] contentBytes, string contentType = "application/json") diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs index bdcf9d9884..de891c2af5 100644 --- a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs +++ b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs @@ -12,6 +12,8 @@ using Microsoft.AspNet.Mvc.Internal; using Microsoft.AspNet.Routing; using Microsoft.AspNet.Testing; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; using Microsoft.Net.Http.Headers; using Moq; using Newtonsoft.Json; @@ -40,7 +42,8 @@ public void Constructor_UsesSerializerSettings() // Arrange // Act var serializerSettings = new JsonSerializerSettings(); - var jsonFormatter = new JsonInputFormatter(serializerSettings); + var logger = GetLogger(); + var jsonFormatter = new JsonInputFormatter(logger, serializerSettings); // Assert Assert.Same(serializerSettings, jsonFormatter.SerializerSettings); @@ -290,6 +293,11 @@ private static Encoding CreateOrGetSupportedEncoding( return encoding; } + private static ILogger GetLogger() + { + return NullLogger.Instance; + } + private static OutputFormatterWriteContext GetOutputFormatterContext( object outputValue, Type outputType, diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonPatchInputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonPatchInputFormatterTest.cs index e42eacf9ad..19985d2f2b 100644 --- a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonPatchInputFormatterTest.cs +++ b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonPatchInputFormatterTest.cs @@ -8,6 +8,8 @@ using Microsoft.AspNet.Http; using Microsoft.AspNet.JsonPatch; using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; using Moq; using Xunit; @@ -19,7 +21,8 @@ public class JsonPatchInputFormatterTest public async Task JsonPatchInputFormatter_ReadsOneOperation_Successfully() { // Arrange - var formatter = new JsonPatchInputFormatter(); + var logger = GetLogger(); + var formatter = new JsonPatchInputFormatter(logger); var content = "[{\"op\":\"add\",\"path\":\"Customer/Name\",\"value\":\"John\"}]"; var contentBytes = Encoding.UTF8.GetBytes(content); @@ -49,7 +52,8 @@ public async Task JsonPatchInputFormatter_ReadsOneOperation_Successfully() public async Task JsonPatchInputFormatter_ReadsMultipleOperations_Successfully() { // Arrange - var formatter = new JsonPatchInputFormatter(); + var logger = GetLogger(); + var formatter = new JsonPatchInputFormatter(logger); var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}," + "{\"op\": \"remove\", \"path\" : \"Customer/Name\"}]"; var contentBytes = Encoding.UTF8.GetBytes(content); @@ -86,7 +90,8 @@ public async Task JsonPatchInputFormatter_ReadsMultipleOperations_Successfully() public void CanRead_ReturnsTrueOnlyForJsonPatchContentType(string requestContentType, bool expectedCanRead) { // Arrange - var formatter = new JsonPatchInputFormatter(); + var logger = GetLogger(); + var formatter = new JsonPatchInputFormatter(logger); var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]"; var contentBytes = Encoding.UTF8.GetBytes(content); @@ -114,7 +119,8 @@ public void CanRead_ReturnsTrueOnlyForJsonPatchContentType(string requestContent public void CanRead_ReturnsFalse_NonJsonPatchContentType(Type modelType) { // Arrange - var formatter = new JsonPatchInputFormatter(); + var logger = GetLogger(); + var formatter = new JsonPatchInputFormatter(logger); var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]"; var contentBytes = Encoding.UTF8.GetBytes(content); @@ -143,7 +149,8 @@ public async Task JsonPatchInputFormatter_ReturnsModelStateErrors_InvalidModelTy 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 "; - var formatter = new JsonPatchInputFormatter(); + var logger = GetLogger(); + var formatter = new JsonPatchInputFormatter(logger); var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]"; var contentBytes = Encoding.UTF8.GetBytes(content); @@ -166,6 +173,11 @@ public async Task JsonPatchInputFormatter_ReturnsModelStateErrors_InvalidModelTy Assert.Contains(exceptionMessage, modelState[""].Errors[0].Exception.Message); } + private static ILogger GetLogger() + { + return NullLogger.Instance; + } + private static HttpContext GetHttpContext( byte[] contentBytes, string contentType = "application/json-patch+json") diff --git a/test/Microsoft.AspNet.Mvc.IntegrationTests/ModelBindingTestHelper.cs b/test/Microsoft.AspNet.Mvc.IntegrationTests/ModelBindingTestHelper.cs index 5a6e1dd08c..082d9aa16f 100644 --- a/test/Microsoft.AspNet.Mvc.IntegrationTests/ModelBindingTestHelper.cs +++ b/test/Microsoft.AspNet.Mvc.IntegrationTests/ModelBindingTestHelper.cs @@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.ModelBinding.Validation; using Microsoft.AspNet.Routing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.OptionsModel; namespace Microsoft.AspNet.Mvc.IntegrationTests @@ -70,6 +71,7 @@ private static HttpContext GetHttpContext( var serviceCollection = new ServiceCollection(); serviceCollection.AddMvc(); + serviceCollection.AddTransient(); if (updateOptions != null) { diff --git a/test/Microsoft.AspNet.Mvc.IntegrationTests/TestMvcOptions.cs b/test/Microsoft.AspNet.Mvc.IntegrationTests/TestMvcOptions.cs index c57f76e676..8d0fff696b 100644 --- a/test/Microsoft.AspNet.Mvc.IntegrationTests/TestMvcOptions.cs +++ b/test/Microsoft.AspNet.Mvc.IntegrationTests/TestMvcOptions.cs @@ -5,6 +5,7 @@ using Microsoft.AspNet.Mvc.Formatters.Json.Internal; using Microsoft.AspNet.Mvc.Internal; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.OptionsModel; namespace Microsoft.AspNet.Mvc.IntegrationTests @@ -19,7 +20,11 @@ public TestMvcOptions() MvcDataAnnotationsMvcOptionsSetup.ConfigureMvc( Value, collection.BuildServiceProvider()); - MvcJsonMvcOptionsSetup.ConfigureMvc(Value, SerializerSettingsProvider.CreateSerializerSettings()); + + var loggerFactory = new LoggerFactory(); + var serializerSettings = SerializerSettingsProvider.CreateSerializerSettings(); + + MvcJsonMvcOptionsSetup.ConfigureMvc(Value, serializerSettings, loggerFactory); } public MvcOptions Value { get; } diff --git a/test/Microsoft.AspNet.Mvc.Test/MvcOptionsSetupTest.cs b/test/Microsoft.AspNet.Mvc.Test/MvcOptionsSetupTest.cs index fc31fbdab6..295c162393 100644 --- a/test/Microsoft.AspNet.Mvc.Test/MvcOptionsSetupTest.cs +++ b/test/Microsoft.AspNet.Mvc.Test/MvcOptionsSetupTest.cs @@ -18,6 +18,7 @@ using Moq; using Newtonsoft.Json.Linq; using Xunit; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNet.Mvc { @@ -191,7 +192,10 @@ var xObjectFilter public void Setup_JsonFormattersUseSerializerSettings() { // Arrange - var services = GetServiceProvider(); + var services = GetServiceProvider(s => + { + s.AddTransient(); + }); // Act var options = services.GetRequiredService>().Value; @@ -222,7 +226,7 @@ private static IServiceProvider GetServiceProvider(Action ac { var serviceCollection = new ServiceCollection(); serviceCollection.AddMvc(); - + serviceCollection.AddTransient(); if (action != null) { action(serviceCollection); diff --git a/test/WebSites/ApiExplorerWebSite/Startup.cs b/test/WebSites/ApiExplorerWebSite/Startup.cs index 85e9c28d1f..3d99d1ea07 100644 --- a/test/WebSites/ApiExplorerWebSite/Startup.cs +++ b/test/WebSites/ApiExplorerWebSite/Startup.cs @@ -2,9 +2,9 @@ // 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.Mvc; using Microsoft.AspNet.Mvc.Formatters; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace ApiExplorerWebSite { @@ -13,6 +13,7 @@ public class Startup // Set up application services public void ConfigureServices(IServiceCollection services) { + services.AddTransient(); services.AddMvc(options => { options.Filters.AddService(typeof(ApiExplorerDataFilter)); diff --git a/test/WebSites/BasicWebSite/Controllers/SpecificFormattersController.cs b/test/WebSites/BasicWebSite/Controllers/SpecificFormattersController.cs index dc0de3896e..e3e5184797 100644 --- a/test/WebSites/BasicWebSite/Controllers/SpecificFormattersController.cs +++ b/test/WebSites/BasicWebSite/Controllers/SpecificFormattersController.cs @@ -5,6 +5,8 @@ using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Formatters; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -61,8 +63,9 @@ public void OnResourceExecuting(ResourceExecutingContext context) // Instead remove and add new formatters which only effects the controllers this // attribute is decorated on. context.InputFormatters.RemoveType(); - context.InputFormatters.Add(new JsonInputFormatter(_serializerSettings)); - + var loggerFactory = context.HttpContext.RequestServices.GetRequiredService(); + var logger = loggerFactory.CreateLogger(); + context.InputFormatters.Add(new JsonInputFormatter(logger ,_serializerSettings)); } public void OnResultExecuted(ResultExecutedContext context) diff --git a/test/WebSites/BasicWebSite/Startup.cs b/test/WebSites/BasicWebSite/Startup.cs index cf505eedaf..1a619ac3c3 100644 --- a/test/WebSites/BasicWebSite/Startup.cs +++ b/test/WebSites/BasicWebSite/Startup.cs @@ -16,7 +16,7 @@ public void ConfigureServices(IServiceCollection services) { options.Conventions.Add(new ApplicationDescription("This is a basic website.")); }); - + services.AddLogging(); services.AddSingleton(); }