Add explicit content types to 'no formatter' logging (#11213)

* Add explicit content types to 'no formatter' logging

* Remove dead code
This commit is contained in:
Kristian Hellang 2019-06-26 00:07:35 +02:00 committed by Ryan Nowak
parent 0274aceaee
commit 7003fb53d5
4 changed files with 49 additions and 14 deletions

View File

@ -147,14 +147,11 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
}
}
if (selectedFormatter == null)
if (selectedFormatter != null)
{
// No formatter supports this.
_logger.NoFormatter(context);
return null;
_logger.FormatterSelected(selectedFormatter, context);
}
_logger.FormatterSelected(selectedFormatter, context);
return selectedFormatter;
}

View File

@ -148,7 +148,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
if (selectedFormatter == null)
{
// No formatter supports this.
Logger.NoFormatter(formatterContext);
Logger.NoFormatter(formatterContext, result.ContentTypes);
context.HttpContext.Response.StatusCode = StatusCodes.Status406NotAcceptable;
return Task.CompletedTask;

View File

@ -4,7 +4,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
@ -28,8 +27,6 @@ namespace Microsoft.AspNetCore.Mvc
public const string ActionFilter = "Action Filter";
private static readonly string[] _noFilters = new[] { "None" };
private static readonly double TimestampToTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
private static readonly Action<ILogger, string, string, Exception> _actionExecuting;
private static readonly Action<ILogger, string, MethodInfo, string, string, Exception> _controllerActionExecuting;
private static readonly Action<ILogger, string, double, Exception> _actionExecuted;
@ -73,7 +70,7 @@ namespace Microsoft.AspNetCore.Mvc
private static readonly Action<ILogger, string, Exception> _localRedirectResultExecuting;
private static readonly Action<ILogger, string, Exception> _objectResultExecuting;
private static readonly Action<ILogger, string, Exception> _noFormatter;
private static readonly Action<ILogger, IEnumerable<string>, Exception> _noFormatter;
private static readonly Action<ILogger, IOutputFormatter, string, Exception> _formatterSelected;
private static readonly Action<ILogger, string, Exception> _skippedContentNegotiation;
private static readonly Action<ILogger, Exception> _noAcceptForNegotiation;
@ -300,10 +297,10 @@ namespace Microsoft.AspNetCore.Mvc
new EventId(1, "LocalRedirectResultExecuting"),
"Executing LocalRedirectResult, redirecting to {Destination}.");
_noFormatter = LoggerMessage.Define<string>(
_noFormatter = LoggerMessage.Define<IEnumerable<string>>(
LogLevel.Warning,
new EventId(1, "NoFormatter"),
"No output formatter was found for content type '{ContentType}' to write the response.");
"No output formatter was found for content types '{ContentTypes}' to write the response.");
_objectResultExecuting = LoggerMessage.Define<string>(
LogLevel.Information,
@ -1017,11 +1014,19 @@ namespace Microsoft.AspNetCore.Mvc
public static void NoFormatter(
this ILogger logger,
OutputFormatterCanWriteContext formatterContext)
OutputFormatterCanWriteContext context,
MediaTypeCollection contentTypes)
{
if (logger.IsEnabled(LogLevel.Warning))
{
_noFormatter(logger, Convert.ToString(formatterContext.ContentType), null);
var considered = new List<string>(contentTypes);
if (context.ContentType.HasValue)
{
considered.Add(Convert.ToString(context.ContentType));
}
_noFormatter(logger, considered, null);
}
}

View File

@ -1,7 +1,9 @@
// 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.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Logging.Testing;
using Moq;
using Xunit;
@ -282,6 +284,37 @@ namespace Microsoft.AspNetCore.Mvc
write.State.ToString());
}
[Fact]
public void NoFormatter_LogsListOfContentTypes()
{
// Arrange
var testSink = new TestSink();
var loggerFactory = new TestLoggerFactory(testSink, enabled: true);
var logger = loggerFactory.CreateLogger("test");
var mediaTypes = new MediaTypeCollection
{
"application/problem+json",
"application/problem+xml",
};
var httpContext = Mock.Of<HttpContext>();
var context = new Mock<OutputFormatterCanWriteContext>(httpContext);
context.SetupGet(x => x.ContentType).Returns("application/json");
// Act
logger.NoFormatter(context.Object, mediaTypes);
// Assert
var write = Assert.Single(testSink.Writes);
Assert.Equal(
"No output formatter was found for content types " +
"'application/problem+json, application/problem+xml, application/json'" +
" to write the response.",
write.State.ToString());
}
public interface IOrderedAuthorizeFilter : IAuthorizationFilter, IAsyncAuthorizationFilter, IOrderedFilter { }
public interface IOrderedResourceFilter : IResourceFilter, IAsyncResourceFilter, IOrderedFilter { }