File results - logging

This commit is contained in:
Kiran Challa 2017-12-27 17:06:55 -08:00
parent 997544077a
commit 40d027fca3
10 changed files with 185 additions and 47 deletions

View File

@ -1551,7 +1551,7 @@ namespace Microsoft.AspNetCore.Mvc
/// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or /// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or
/// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable). /// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable).
/// </summary> /// </summary>
/// <param name="physicalPath">The physical path of the file to be returned.</param> /// <param name="physicalPath">The path to the file. The path must be an absolute path.</param>
/// <param name="contentType">The Content-Type of the file.</param> /// <param name="contentType">The Content-Type of the file.</param>
/// <returns>The created <see cref="PhysicalFileResult"/> for the response.</returns> /// <returns>The created <see cref="PhysicalFileResult"/> for the response.</returns>
[NonAction] [NonAction]
@ -1564,7 +1564,7 @@ namespace Microsoft.AspNetCore.Mvc
/// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or /// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or
/// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable). /// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable).
/// </summary> /// </summary>
/// <param name="physicalPath">The physical path of the file to be returned.</param> /// <param name="physicalPath">The path to the file. The path must be an absolute path.</param>
/// <param name="contentType">The Content-Type of the file.</param> /// <param name="contentType">The Content-Type of the file.</param>
/// <param name="enableRangeProcessing">Set to <c>true</c> to enable range requests processing.</param> /// <param name="enableRangeProcessing">Set to <c>true</c> to enable range requests processing.</param>
/// <returns>The created <see cref="PhysicalFileResult"/> for the response.</returns> /// <returns>The created <see cref="PhysicalFileResult"/> for the response.</returns>
@ -1579,7 +1579,7 @@ namespace Microsoft.AspNetCore.Mvc
/// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or /// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or
/// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable). /// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable).
/// </summary> /// </summary>
/// <param name="physicalPath">The physical path of the file to be returned.</param> /// <param name="physicalPath">The path to the file. The path must be an absolute path.</param>
/// <param name="contentType">The Content-Type of the file.</param> /// <param name="contentType">The Content-Type of the file.</param>
/// <param name="fileDownloadName">The suggested file name.</param> /// <param name="fileDownloadName">The suggested file name.</param>
/// <returns>The created <see cref="PhysicalFileResult"/> for the response.</returns> /// <returns>The created <see cref="PhysicalFileResult"/> for the response.</returns>
@ -1597,7 +1597,7 @@ namespace Microsoft.AspNetCore.Mvc
/// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or /// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or
/// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable). /// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable).
/// </summary> /// </summary>
/// <param name="physicalPath">The physical path of the file to be returned.</param> /// <param name="physicalPath">The path to the file. The path must be an absolute path.</param>
/// <param name="contentType">The Content-Type of the file.</param> /// <param name="contentType">The Content-Type of the file.</param>
/// <param name="fileDownloadName">The suggested file name.</param> /// <param name="fileDownloadName">The suggested file name.</param>
/// <param name="enableRangeProcessing">Set to <c>true</c> to enable range requests processing.</param> /// <param name="enableRangeProcessing">Set to <c>true</c> to enable range requests processing.</param>
@ -1620,7 +1620,7 @@ namespace Microsoft.AspNetCore.Mvc
/// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or /// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or
/// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable). /// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable).
/// </summary> /// </summary>
/// <param name="physicalPath">The physical path of the file to be returned.</param> /// <param name="physicalPath">The path to the file. The path must be an absolute path.</param>
/// <param name="contentType">The Content-Type of the file.</param> /// <param name="contentType">The Content-Type of the file.</param>
/// <param name="lastModified">The <see cref="DateTimeOffset"/> of when the file was last modified.</param> /// <param name="lastModified">The <see cref="DateTimeOffset"/> of when the file was last modified.</param>
/// <param name="entityTag">The <see cref="EntityTagHeaderValue"/> associated with the file.</param> /// <param name="entityTag">The <see cref="EntityTagHeaderValue"/> associated with the file.</param>
@ -1641,7 +1641,7 @@ namespace Microsoft.AspNetCore.Mvc
/// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or /// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or
/// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable). /// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable).
/// </summary> /// </summary>
/// <param name="physicalPath">The physical path of the file to be returned.</param> /// <param name="physicalPath">The path to the file. The path must be an absolute path.</param>
/// <param name="contentType">The Content-Type of the file.</param> /// <param name="contentType">The Content-Type of the file.</param>
/// <param name="lastModified">The <see cref="DateTimeOffset"/> of when the file was last modified.</param> /// <param name="lastModified">The <see cref="DateTimeOffset"/> of when the file was last modified.</param>
/// <param name="entityTag">The <see cref="EntityTagHeaderValue"/> associated with the file.</param> /// <param name="entityTag">The <see cref="EntityTagHeaderValue"/> associated with the file.</param>
@ -1664,7 +1664,7 @@ namespace Microsoft.AspNetCore.Mvc
/// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or /// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or
/// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable). /// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable).
/// </summary> /// </summary>
/// <param name="physicalPath">The physical path of the file to be returned.</param> /// <param name="physicalPath">The path to the file. The path must be an absolute path.</param>
/// <param name="contentType">The Content-Type of the file.</param> /// <param name="contentType">The Content-Type of the file.</param>
/// <param name="fileDownloadName">The suggested file name.</param> /// <param name="fileDownloadName">The suggested file name.</param>
/// <param name="lastModified">The <see cref="DateTimeOffset"/> of when the file was last modified.</param> /// <param name="lastModified">The <see cref="DateTimeOffset"/> of when the file was last modified.</param>
@ -1687,7 +1687,7 @@ namespace Microsoft.AspNetCore.Mvc
/// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or /// This supports range requests (<see cref="StatusCodes.Status206PartialContent"/> or
/// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable). /// <see cref="StatusCodes.Status416RangeNotSatisfiable"/> if the range is not satisfiable).
/// </summary> /// </summary>
/// <param name="physicalPath">The physical path of the file to be returned.</param> /// <param name="physicalPath">The path to the file. The path must be an absolute path.</param>
/// <param name="contentType">The Content-Type of the file.</param> /// <param name="contentType">The Content-Type of the file.</param>
/// <param name="fileDownloadName">The suggested file name.</param> /// <param name="fileDownloadName">The suggested file name.</param>
/// <param name="lastModified">The <see cref="DateTimeOffset"/> of when the file was last modified.</param> /// <param name="lastModified">The <see cref="DateTimeOffset"/> of when the file was last modified.</param>

View File

@ -4,6 +4,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
@ -29,6 +30,8 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
throw new ArgumentNullException(nameof(result)); throw new ArgumentNullException(nameof(result));
} }
Logger.ExecutingFileResult(result);
var (range, rangeLength, serveBody) = SetHeadersAndLog( var (range, rangeLength, serveBody) = SetHeadersAndLog(
context, context,
result, result,
@ -62,6 +65,11 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
return Task.CompletedTask; return Task.CompletedTask;
} }
if (range != null)
{
Logger.WritingRangeToBody();
}
var fileContentStream = new MemoryStream(result.FileContents); var fileContentStream = new MemoryStream(result.FileContents);
return WriteFileAsync(context.HttpContext, fileContentStream, range, rangeLength); return WriteFileAsync(context.HttpContext, fileContentStream, range, rangeLength);
} }

View File

@ -56,7 +56,6 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
SetContentType(context, result); SetContentType(context, result);
SetContentDispositionHeader(context, result); SetContentDispositionHeader(context, result);
Logger.FileResultExecuting(result.FileDownloadName);
var request = context.HttpContext.Request; var request = context.HttpContext.Request;
var httpRequestHeaders = request.GetTypedHeaders(); var httpRequestHeaders = request.GetTypedHeaders();
@ -106,6 +105,10 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
return SetRangeHeaders(context, httpRequestHeaders, fileLength.Value); return SetRangeHeaders(context, httpRequestHeaders, fileLength.Value);
} }
} }
else
{
Logger.NotEnabledForRangeProcessing();
}
} }
return (range: null, rangeLength: 0, serveBody); return (range: null, rangeLength: 0, serveBody);
@ -150,7 +153,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
response.Headers[HeaderNames.AcceptRanges] = AcceptRangeHeaderValue; response.Headers[HeaderNames.AcceptRanges] = AcceptRangeHeaderValue;
} }
internal static bool IfRangeValid( internal bool IfRangeValid(
RequestHeaders httpRequestHeaders, RequestHeaders httpRequestHeaders,
DateTimeOffset? lastModified = null, DateTimeOffset? lastModified = null,
EntityTagHeaderValue etag = null) EntityTagHeaderValue etag = null)
@ -168,11 +171,13 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
{ {
if (lastModified.HasValue && lastModified > ifRange.LastModified) if (lastModified.HasValue && lastModified > ifRange.LastModified)
{ {
Logger.IfRangeLastModifiedPreconditionFailed(lastModified, ifRange.LastModified);
return false; return false;
} }
} }
else if (etag != null && ifRange.EntityTag != null && !ifRange.EntityTag.Compare(etag, useStrongComparison: true)) else if (etag != null && ifRange.EntityTag != null && !ifRange.EntityTag.Compare(etag, useStrongComparison: true))
{ {
Logger.IfRangeETagPreconditionFailed(etag, ifRange.EntityTag);
return false; return false;
} }
} }
@ -181,7 +186,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
} }
// Internal for testing // Internal for testing
internal static PreconditionState GetPreconditionState( internal PreconditionState GetPreconditionState(
RequestHeaders httpRequestHeaders, RequestHeaders httpRequestHeaders,
DateTimeOffset? lastModified = null, DateTimeOffset? lastModified = null,
EntityTagHeaderValue etag = null) EntityTagHeaderValue etag = null)
@ -200,6 +205,11 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
etag: etag, etag: etag,
matchFoundState: PreconditionState.ShouldProcess, matchFoundState: PreconditionState.ShouldProcess,
matchNotFoundState: PreconditionState.PreconditionFailed); matchNotFoundState: PreconditionState.PreconditionFailed);
if (ifMatchState == PreconditionState.PreconditionFailed)
{
Logger.IfMatchPreconditionFailed(etag);
}
} }
// 14.26 If-None-Match // 14.26 If-None-Match
@ -229,6 +239,11 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
{ {
var unmodified = ifUnmodifiedSince >= lastModified; var unmodified = ifUnmodifiedSince >= lastModified;
ifUnmodifiedSinceState = unmodified ? PreconditionState.ShouldProcess : PreconditionState.PreconditionFailed; ifUnmodifiedSinceState = unmodified ? PreconditionState.ShouldProcess : PreconditionState.PreconditionFailed;
if (ifUnmodifiedSinceState == PreconditionState.PreconditionFailed)
{
Logger.IfUnmodifiedSincePreconditionFailed(lastModified, ifUnmodifiedSince);
}
} }
var state = GetMaxPreconditionState(ifMatchState, ifNoneMatchState, ifModifiedSinceState, ifUnmodifiedSinceState); var state = GetMaxPreconditionState(ifMatchState, ifNoneMatchState, ifModifiedSinceState, ifUnmodifiedSinceState);
@ -273,7 +288,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
return max; return max;
} }
private static (RangeItemHeaderValue range, long rangeLength, bool serveBody) SetRangeHeaders( private (RangeItemHeaderValue range, long rangeLength, bool serveBody) SetRangeHeaders(
ActionContext context, ActionContext context,
RequestHeaders httpRequestHeaders, RequestHeaders httpRequestHeaders,
long fileLength) long fileLength)
@ -286,7 +301,8 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
var (isRangeRequest, range) = RangeHelper.ParseRange( var (isRangeRequest, range) = RangeHelper.ParseRange(
context.HttpContext, context.HttpContext,
httpRequestHeaders, httpRequestHeaders,
fileLength); fileLength,
Logger);
if (!isRangeRequest) if (!isRangeRequest)
{ {

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
@ -28,6 +29,8 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
throw new ArgumentNullException(nameof(result)); throw new ArgumentNullException(nameof(result));
} }
Logger.ExecutingFileResult(result);
long? fileLength = null; long? fileLength = null;
if (result.FileStream.CanSeek) if (result.FileStream.CanSeek)
{ {
@ -67,6 +70,11 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
return Task.CompletedTask; return Task.CompletedTask;
} }
if (range != null)
{
Logger.WritingRangeToBody();
}
return WriteFileAsync(context.HttpContext, result.FileStream, range, rangeLength); return WriteFileAsync(context.HttpContext, result.FileStream, range, rangeLength);
} }
} }

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
@ -39,6 +40,8 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
Resources.FormatFileResult_InvalidPath(result.FileName), result.FileName); Resources.FormatFileResult_InvalidPath(result.FileName), result.FileName);
} }
Logger.ExecutingFileResult(result, result.FileName);
var lastModified = result.LastModified ?? fileInfo.LastModified; var lastModified = result.LastModified ?? fileInfo.LastModified;
var (range, rangeLength, serveBody) = SetHeadersAndLog( var (range, rangeLength, serveBody) = SetHeadersAndLog(
context, context,
@ -79,6 +82,11 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
throw new NotSupportedException(Resources.FormatFileResult_PathNotRooted(result.FileName)); throw new NotSupportedException(Resources.FormatFileResult_PathNotRooted(result.FileName));
} }
if (range != null)
{
Logger.WritingRangeToBody();
}
var sendFile = response.HttpContext.Features.Get<IHttpSendFileFeature>(); var sendFile = response.HttpContext.Features.Get<IHttpSendFileFeature>();
if (sendFile != null) if (sendFile != null)
{ {

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
@ -49,6 +50,8 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
Resources.FormatFileResult_InvalidPath(result.FileName), result.FileName); Resources.FormatFileResult_InvalidPath(result.FileName), result.FileName);
} }
Logger.ExecutingFileResult(result, result.FileName);
var lastModified = result.LastModified ?? fileInfo.LastModified; var lastModified = result.LastModified ?? fileInfo.LastModified;
var (range, rangeLength, serveBody) = SetHeadersAndLog( var (range, rangeLength, serveBody) = SetHeadersAndLog(
context, context,
@ -85,6 +88,12 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
var response = context.HttpContext.Response; var response = context.HttpContext.Response;
var physicalPath = fileInfo.PhysicalPath; var physicalPath = fileInfo.PhysicalPath;
if (range != null)
{
Logger.WritingRangeToBody();
}
var sendFile = response.HttpContext.Features.Get<IHttpSendFileFeature>(); var sendFile = response.HttpContext.Features.Get<IHttpSendFileFeature>();
if (sendFile != null && !string.IsNullOrEmpty(physicalPath)) if (sendFile != null && !string.IsNullOrEmpty(physicalPath))
{ {
@ -110,6 +119,10 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
private IFileInfo GetFileInformation(VirtualFileResult result) private IFileInfo GetFileInformation(VirtualFileResult result)
{ {
var fileProvider = GetFileProvider(result); var fileProvider = GetFileProvider(result);
if (fileProvider is NullFileProvider)
{
throw new InvalidOperationException(Resources.VirtualFileResultExecutor_NoFileProviderConfigured);
}
var normalizedPath = result.FileName; var normalizedPath = result.FileName;
if (normalizedPath.StartsWith("~", StringComparison.Ordinal)) if (normalizedPath.StartsWith("~", StringComparison.Ordinal))

View File

@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Formatters.Internal; using Microsoft.AspNetCore.Mvc.Formatters.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Mvc.Internal namespace Microsoft.AspNetCore.Mvc.Internal
{ {
@ -45,8 +46,10 @@ namespace Microsoft.AspNetCore.Mvc.Internal
private static readonly Action<ILogger, string, Exception> _ambiguousActions; private static readonly Action<ILogger, string, Exception> _ambiguousActions;
private static readonly Action<ILogger, string, string, IActionConstraint, Exception> _constraintMismatch; private static readonly Action<ILogger, string, string, IActionConstraint, Exception> _constraintMismatch;
private static readonly Action<ILogger, string, Exception> _fileResultExecuting; private static readonly Action<ILogger, FileResult, string, string, Exception> _executingFileResult;
private static readonly Action<ILogger, FileResult, string, Exception> _executingFileResultWithNoFileName;
private static readonly Action<ILogger, Exception> _notEnabledForRangeProcessing;
private static readonly Action<ILogger, Exception> _writingRangeToBody;
private static readonly Action<ILogger, object, Exception> _authorizationFailure; private static readonly Action<ILogger, object, Exception> _authorizationFailure;
private static readonly Action<ILogger, object, Exception> _resourceFilterShortCircuit; private static readonly Action<ILogger, object, Exception> _resourceFilterShortCircuit;
private static readonly Action<ILogger, object, Exception> _resultFilterShortCircuit; private static readonly Action<ILogger, object, Exception> _resultFilterShortCircuit;
@ -101,6 +104,10 @@ namespace Microsoft.AspNetCore.Mvc.Internal
private static readonly Action<ILogger, string, Exception> _cannotApplyFormatFilterContentType; private static readonly Action<ILogger, string, Exception> _cannotApplyFormatFilterContentType;
private static readonly Action<ILogger, Exception> _actionDoesNotExplicitlySpecifyContentTypes; private static readonly Action<ILogger, Exception> _actionDoesNotExplicitlySpecifyContentTypes;
private static readonly Action<ILogger, IEnumerable<MediaTypeSegmentWithQuality>, Exception> _selectingOutputFormatterUsingAcceptHeader; private static readonly Action<ILogger, IEnumerable<MediaTypeSegmentWithQuality>, Exception> _selectingOutputFormatterUsingAcceptHeader;
private static readonly Action<ILogger, EntityTagHeaderValue, Exception> _ifMatchPreconditionFailed;
private static readonly Action<ILogger, DateTimeOffset?, DateTimeOffset?, Exception> _ifUnmodifiedSincePreconditionFailed;
private static readonly Action<ILogger, DateTimeOffset?, DateTimeOffset?, Exception> _ifRangeLastModifiedPreconditionFailed;
private static readonly Action<ILogger, EntityTagHeaderValue, EntityTagHeaderValue, Exception> _ifRangeETagPreconditionFailed;
private static readonly Action<ILogger, IEnumerable<MediaTypeSegmentWithQuality>, MediaTypeCollection, Exception> _selectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes; private static readonly Action<ILogger, IEnumerable<MediaTypeSegmentWithQuality>, MediaTypeCollection, Exception> _selectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes;
private static readonly Action<ILogger, Exception> _selectingOutputFormatterWithoutUsingContentTypes; private static readonly Action<ILogger, Exception> _selectingOutputFormatterWithoutUsingContentTypes;
private static readonly Action<ILogger, MediaTypeCollection, Exception> _selectingOutputFormatterUsingContentTypes; private static readonly Action<ILogger, MediaTypeCollection, Exception> _selectingOutputFormatterUsingContentTypes;
@ -175,10 +182,15 @@ namespace Microsoft.AspNetCore.Mvc.Internal
2, 2,
"Action '{ActionName}' with id '{ActionId}' did not match the constraint '{ActionConstraint}'"); "Action '{ActionName}' with id '{ActionId}' did not match the constraint '{ActionConstraint}'");
_fileResultExecuting = LoggerMessage.Define<string>( _executingFileResult = LoggerMessage.Define<FileResult, string, string>(
LogLevel.Information, LogLevel.Information,
1, 1,
"Executing FileResult, sending file as {FileDownloadName}"); "Executing {FileResultType}, sending file '{FileDownloadPath}' with download name '{FileDownloadName}' ...");
_executingFileResultWithNoFileName = LoggerMessage.Define<FileResult, string>(
LogLevel.Information,
2,
"Executing {FileResultType}, sending file with download name '{FileDownloadName}' ...");
_authorizationFailure = LoggerMessage.Define<object>( _authorizationFailure = LoggerMessage.Define<object>(
LogLevel.Information, LogLevel.Information,
@ -404,6 +416,36 @@ namespace Microsoft.AspNetCore.Mvc.Internal
LogLevel.Debug, LogLevel.Debug,
11, 11,
"List of registered output formatters, in the following order: {OutputFormatters}"); "List of registered output formatters, in the following order: {OutputFormatters}");
_ifMatchPreconditionFailed = LoggerMessage.Define<EntityTagHeaderValue>(
LogLevel.Debug,
12,
"Current request's If-Match header check failed as the file's current etag '{CurrentETag}' does not match with any of the supplied etags.");
_ifUnmodifiedSincePreconditionFailed = LoggerMessage.Define<DateTimeOffset?, DateTimeOffset?>(
LogLevel.Debug,
13,
"Current request's If-Unmodified-Since header check failed as the file was modified (at '{lastModified}') after the If-Unmodified-Since date '{IfUnmodifiedSinceDate}'.");
_ifRangeLastModifiedPreconditionFailed = LoggerMessage.Define<DateTimeOffset?, DateTimeOffset?>(
LogLevel.Debug,
14,
"Could not serve range as the file was modified (at {LastModified}) after the if-Range's last modified date '{IfRangeLastModified}'.");
_ifRangeETagPreconditionFailed = LoggerMessage.Define<EntityTagHeaderValue, EntityTagHeaderValue>(
LogLevel.Debug,
15,
"Could not serve range as the file's current etag '{CurrentETag}' does not match the If-Range etag '{IfRangeETag}'.");
_notEnabledForRangeProcessing = LoggerMessage.Define(
LogLevel.Debug,
16,
$"The file result has not been enabled for processing range requests. To enable it, set the property '{nameof(FileResult.EnableRangeProcessing)}' on the result to 'true'.");
_writingRangeToBody = LoggerMessage.Define(
LogLevel.Debug,
17,
"Writing the requested range of bytes to the body...");
} }
public static void RegisteredOutputFormatters(this ILogger logger, IEnumerable<IOutputFormatter> outputFormatters) public static void RegisteredOutputFormatters(this ILogger logger, IEnumerable<IOutputFormatter> outputFormatters)
@ -412,8 +454,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
} }
public static void SelectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes( public static void SelectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes(
this ILogger logger, this ILogger logger,
IEnumerable<MediaTypeSegmentWithQuality> acceptHeader, IEnumerable<MediaTypeSegmentWithQuality> acceptHeader,
MediaTypeCollection mediaTypeCollection) MediaTypeCollection mediaTypeCollection)
{ {
_selectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes(logger, acceptHeader, mediaTypeCollection, null); _selectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes(logger, acceptHeader, mediaTypeCollection, null);
@ -624,9 +666,24 @@ namespace Microsoft.AspNetCore.Mvc.Internal
_constraintMismatch(logger, actionName, actionId, actionConstraint, null); _constraintMismatch(logger, actionName, actionId, actionConstraint, null);
} }
public static void FileResultExecuting(this ILogger logger, string fileDownloadName) public static void ExecutingFileResult(this ILogger logger, FileResult fileResult)
{ {
_fileResultExecuting(logger, fileDownloadName, null); _executingFileResultWithNoFileName(logger, fileResult, fileResult.FileDownloadName, null);
}
public static void ExecutingFileResult(this ILogger logger, FileResult fileResult, string fileName)
{
_executingFileResult(logger, fileResult, fileName, fileResult.FileDownloadName, null);
}
public static void NotEnabledForRangeProcessing(this ILogger logger)
{
_notEnabledForRangeProcessing(logger, null);
}
public static void WritingRangeToBody(this ILogger logger)
{
_writingRangeToBody(logger, null);
} }
public static void AuthorizationFailure( public static void AuthorizationFailure(
@ -881,6 +938,35 @@ namespace Microsoft.AspNetCore.Mvc.Internal
} }
} }
public static void IfMatchPreconditionFailed(this ILogger logger, EntityTagHeaderValue etag)
{
_ifMatchPreconditionFailed(logger, etag, null);
}
public static void IfUnmodifiedSincePreconditionFailed(
this ILogger logger,
DateTimeOffset? lastModified,
DateTimeOffset? ifUnmodifiedSinceDate)
{
_ifUnmodifiedSincePreconditionFailed(logger, lastModified, ifUnmodifiedSinceDate, null);
}
public static void IfRangeLastModifiedPreconditionFailed(
this ILogger logger,
DateTimeOffset? lastModified,
DateTimeOffset? ifRangeLastModifiedDate)
{
_ifRangeLastModifiedPreconditionFailed(logger, lastModified, ifRangeLastModifiedDate, null);
}
public static void IfRangeETagPreconditionFailed(
this ILogger logger,
EntityTagHeaderValue currentETag,
EntityTagHeaderValue ifRangeTag)
{
_ifRangeETagPreconditionFailed(logger, currentETag, ifRangeTag, null);
}
private static void LogFilterExecutionPlan( private static void LogFilterExecutionPlan(
ILogger logger, ILogger logger,
string filterType, string filterType,

View File

@ -1354,6 +1354,20 @@ namespace Microsoft.AspNetCore.Mvc.Core
internal static string FormatApiController_AttributeRouteRequired(object p0) internal static string FormatApiController_AttributeRouteRequired(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("ApiController_AttributeRouteRequired"), p0); => string.Format(CultureInfo.CurrentCulture, GetString("ApiController_AttributeRouteRequired"), p0);
/// <summary>
/// No file provider has been configured to process the supplied file.
/// </summary>
internal static string VirtualFileResultExecutor_NoFileProviderConfigured
{
get => GetString("VirtualFileResultExecutor_NoFileProviderConfigured");
}
/// <summary>
/// No file provider has been configured to process the supplied file.
/// </summary>
internal static string FormatVirtualFileResultExecutor_NoFileProviderConfigured()
=> GetString("VirtualFileResultExecutor_NoFileProviderConfigured");
private static string GetString(string name, params string[] formatterNames) private static string GetString(string name, params string[] formatterNames)
{ {
var value = _resourceManager.GetString(name); var value = _resourceManager.GetString(name);

View File

@ -418,4 +418,7 @@
<data name="ApiController_AttributeRouteRequired" xml:space="preserve"> <data name="ApiController_AttributeRouteRequired" xml:space="preserve">
<value>Action methods on controllers annotated with {0} must have an attribute route.</value> <value>Action methods on controllers annotated with {0} must have an attribute route.</value>
</data> </data>
<data name="VirtualFileResultExecutor_NoFileProviderConfigured" xml:space="preserve">
<value>No file provider has been configured to process the supplied file.</value>
</data>
</root> </root>

View File

@ -142,28 +142,6 @@ namespace Microsoft.AspNetCore.Mvc
await Assert.ThrowsAsync<InvalidOperationException>(() => result.ExecuteResultAsync(actionContext)); await Assert.ThrowsAsync<InvalidOperationException>(() => result.ExecuteResultAsync(actionContext));
} }
[ConditionalFact]
[FrameworkSkipCondition(RuntimeFrameworks.CLR, SkipReason = "Fails due to dotnet/standard#567")]
public async Task ExecuteResultAsync_LogsInformation_IfCanResolveLoggerFactory()
{
// Arrange
var httpContext = new DefaultHttpContext();
var services = new ServiceCollection();
var loggerSink = new TestSink();
services.AddSingleton<ILoggerFactory>(new TestLoggerFactory(loggerSink, true));
services.AddSingleton<EmptyFileResultExecutor>();
httpContext.RequestServices = services.BuildServiceProvider();
var actionContext = CreateActionContext(httpContext);
var result = new EmptyFileResult("application/my-type");
// Act
await result.ExecuteResultAsync(actionContext);
// Assert
Assert.Single(loggerSink.Writes);
}
public static TheoryData<string, string> ContentDispositionData public static TheoryData<string, string> ContentDispositionData
{ {
get get
@ -302,9 +280,10 @@ namespace Microsoft.AspNetCore.Mvc
httpRequestHeaders.IfUnmodifiedSince = lastModified; httpRequestHeaders.IfUnmodifiedSince = lastModified;
httpRequestHeaders.IfModifiedSince = DateTimeOffset.MinValue.AddDays(1); httpRequestHeaders.IfModifiedSince = DateTimeOffset.MinValue.AddDays(1);
actionContext.HttpContext = httpContext; actionContext.HttpContext = httpContext;
var fileResult = (new Mock<FileResultExecutorBase>(NullLogger.Instance)).Object;
// Act // Act
var state = FileResultExecutorBase.GetPreconditionState( var state = fileResult.GetPreconditionState(
httpRequestHeaders, httpRequestHeaders,
lastModified, lastModified,
etag); etag);
@ -338,9 +317,10 @@ namespace Microsoft.AspNetCore.Mvc
httpRequestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue; httpRequestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue;
httpRequestHeaders.IfModifiedSince = DateTimeOffset.MinValue.AddDays(2); httpRequestHeaders.IfModifiedSince = DateTimeOffset.MinValue.AddDays(2);
actionContext.HttpContext = httpContext; actionContext.HttpContext = httpContext;
var fileResult = (new Mock<FileResultExecutorBase>(NullLogger.Instance)).Object;
// Act // Act
var state = FileResultExecutorBase.GetPreconditionState( var state = fileResult.GetPreconditionState(
httpRequestHeaders, httpRequestHeaders,
lastModified, lastModified,
etag); etag);
@ -373,9 +353,10 @@ namespace Microsoft.AspNetCore.Mvc
}; };
httpRequestHeaders.IfModifiedSince = lastModified; httpRequestHeaders.IfModifiedSince = lastModified;
actionContext.HttpContext = httpContext; actionContext.HttpContext = httpContext;
var fileResult = (new Mock<FileResultExecutorBase>(NullLogger.Instance)).Object;
// Act // Act
var state = FileResultExecutorBase.GetPreconditionState( var state = fileResult.GetPreconditionState(
httpRequestHeaders, httpRequestHeaders,
lastModified, lastModified,
etag); etag);
@ -400,9 +381,10 @@ namespace Microsoft.AspNetCore.Mvc
httpRequestHeaders.IfRange = new RangeConditionHeaderValue(ifRangeString); httpRequestHeaders.IfRange = new RangeConditionHeaderValue(ifRangeString);
httpRequestHeaders.IfModifiedSince = lastModified; httpRequestHeaders.IfModifiedSince = lastModified;
actionContext.HttpContext = httpContext; actionContext.HttpContext = httpContext;
var fileResult = (new Mock<FileResultExecutorBase>(NullLogger.Instance)).Object;
// Act // Act
var ifRangeIsValid = FileResultExecutorBase.IfRangeValid( var ifRangeIsValid = fileResult.IfRangeValid(
httpRequestHeaders, httpRequestHeaders,
lastModified, lastModified,
etag); etag);