diff --git a/src/Mvc/Mvc.Core/src/Filters/DisableRequestSizeLimitFilter.cs b/src/Mvc/Mvc.Core/src/Filters/DisableRequestSizeLimitFilter.cs
index 28e3a0585095..236c18821ad1 100644
--- a/src/Mvc/Mvc.Core/src/Filters/DisableRequestSizeLimitFilter.cs
+++ b/src/Mvc/Mvc.Core/src/Filters/DisableRequestSizeLimitFilter.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Http.Features;
@@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters;
/// A filter that sets
/// to null.
///
-internal class DisableRequestSizeLimitFilter : IAuthorizationFilter, IRequestSizePolicy
+internal partial class DisableRequestSizeLimitFilter : IAuthorizationFilter, IRequestSizePolicy
{
private readonly ILogger _logger;
@@ -39,7 +39,7 @@ public void OnAuthorization(AuthorizationFilterContext context)
var effectivePolicy = context.FindEffectivePolicy();
if (effectivePolicy != null && effectivePolicy != this)
{
- _logger.NotMostEffectiveFilter(GetType(), effectivePolicy.GetType(), typeof(IRequestSizePolicy));
+ Log.NotMostEffectiveFilter(_logger, GetType(), effectivePolicy.GetType(), typeof(IRequestSizePolicy));
return;
}
@@ -47,16 +47,31 @@ public void OnAuthorization(AuthorizationFilterContext context)
if (maxRequestBodySizeFeature == null)
{
- _logger.FeatureNotFound();
+ Log.FeatureNotFound(_logger);
}
else if (maxRequestBodySizeFeature.IsReadOnly)
{
- _logger.FeatureIsReadOnly();
+ Log.FeatureIsReadOnly(_logger);
}
else
{
maxRequestBodySizeFeature.MaxRequestBodySize = null;
- _logger.RequestBodySizeLimitDisabled();
+ Log.RequestBodySizeLimitDisabled(_logger);
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Warning, "A request body size limit could not be applied. This server does not support the IHttpRequestBodySizeFeature.", EventName = "FeatureNotFound")]
+ public static partial void FeatureNotFound(ILogger logger);
+
+ [LoggerMessage(2, LogLevel.Warning, "A request body size limit could not be applied. The IHttpRequestBodySizeFeature for the server is read-only.", EventName = "FeatureIsReadOnly")]
+ public static partial void FeatureIsReadOnly(ILogger logger);
+
+ [LoggerMessage(3, LogLevel.Debug, "The request body size limit has been disabled.", EventName = "RequestBodySizeLimitDisabled")]
+ public static partial void RequestBodySizeLimitDisabled(ILogger logger);
+
+ [LoggerMessage(4, LogLevel.Debug, "Execution of filter {OverriddenFilter} is preempted by filter {OverridingFilter} which is the most effective filter implementing policy {FilterPolicy}.", EventName = "NotMostEffectiveFilter")]
+ public static partial void NotMostEffectiveFilter(ILogger logger, Type overriddenFilter, Type overridingFilter, Type filterPolicy);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Filters/RequestFormLimitsFilter.cs b/src/Mvc/Mvc.Core/src/Filters/RequestFormLimitsFilter.cs
index 503d584238ce..82fce9b7f49e 100644
--- a/src/Mvc/Mvc.Core/src/Filters/RequestFormLimitsFilter.cs
+++ b/src/Mvc/Mvc.Core/src/Filters/RequestFormLimitsFilter.cs
@@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters;
///
/// A filter that configures for the current request.
///
-internal class RequestFormLimitsFilter : IAuthorizationFilter, IRequestFormLimitsPolicy
+internal partial class RequestFormLimitsFilter : IAuthorizationFilter, IRequestFormLimitsPolicy
{
private readonly ILogger _logger;
@@ -30,7 +30,7 @@ public void OnAuthorization(AuthorizationFilterContext context)
var effectivePolicy = context.FindEffectivePolicy();
if (effectivePolicy != null && effectivePolicy != this)
{
- _logger.NotMostEffectiveFilter(GetType(), effectivePolicy.GetType(), typeof(IRequestFormLimitsPolicy));
+ Log.NotMostEffectiveFilter(_logger, GetType(), effectivePolicy.GetType(), typeof(IRequestFormLimitsPolicy));
return;
}
@@ -41,11 +41,23 @@ public void OnAuthorization(AuthorizationFilterContext context)
{
// Request form has not been read yet, so set the limits
features.Set(new FormFeature(context.HttpContext.Request, FormOptions));
- _logger.AppliedRequestFormLimits();
+ Log.AppliedRequestFormLimits(_logger);
}
else
{
- _logger.CannotApplyRequestFormLimits();
+ Log.CannotApplyRequestFormLimits(_logger);
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Warning, "Unable to apply configured form options since the request form has already been read.", EventName = "CannotApplyRequestFormLimits")]
+ public static partial void CannotApplyRequestFormLimits(ILogger logger);
+
+ [LoggerMessage(2, LogLevel.Debug, "Applied the configured form options on the current request.", EventName = "AppliedRequestFormLimits")]
+ public static partial void AppliedRequestFormLimits(ILogger logger);
+
+ [LoggerMessage(4, LogLevel.Debug, "Execution of filter {OverriddenFilter} is preempted by filter {OverridingFilter} which is the most effective filter implementing policy {FilterPolicy}.", EventName = "NotMostEffectiveFilter")]
+ public static partial void NotMostEffectiveFilter(ILogger logger, Type overriddenFilter, Type overridingFilter, Type filterPolicy);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Filters/RequestSizeLimitFilter.cs b/src/Mvc/Mvc.Core/src/Filters/RequestSizeLimitFilter.cs
index 64f4a1ec67ff..abb87f9e34b0 100644
--- a/src/Mvc/Mvc.Core/src/Filters/RequestSizeLimitFilter.cs
+++ b/src/Mvc/Mvc.Core/src/Filters/RequestSizeLimitFilter.cs
@@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters;
/// A filter that sets the
/// to the specified .
///
-internal class RequestSizeLimitFilter : IAuthorizationFilter, IRequestSizePolicy
+internal partial class RequestSizeLimitFilter : IAuthorizationFilter, IRequestSizePolicy
{
private readonly ILogger _logger;
@@ -41,7 +41,7 @@ public void OnAuthorization(AuthorizationFilterContext context)
var effectivePolicy = context.FindEffectivePolicy();
if (effectivePolicy != null && effectivePolicy != this)
{
- _logger.NotMostEffectiveFilter(GetType(), effectivePolicy.GetType(), typeof(IRequestSizePolicy));
+ Log.NotMostEffectiveFilter(_logger, GetType(), effectivePolicy.GetType(), typeof(IRequestSizePolicy));
return;
}
@@ -49,16 +49,31 @@ public void OnAuthorization(AuthorizationFilterContext context)
if (maxRequestBodySizeFeature == null)
{
- _logger.FeatureNotFound();
+ Log.FeatureNotFound(_logger);
}
else if (maxRequestBodySizeFeature.IsReadOnly)
{
- _logger.FeatureIsReadOnly();
+ Log.FeatureIsReadOnly(_logger);
}
else
{
maxRequestBodySizeFeature.MaxRequestBodySize = Bytes;
- _logger.MaxRequestBodySizeSet(Bytes.ToString(CultureInfo.InvariantCulture));
+ Log.MaxRequestBodySizeSet(_logger, Bytes.ToString(CultureInfo.InvariantCulture));
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Warning, "A request body size limit could not be applied. This server does not support the IHttpRequestBodySizeFeature.", EventName = "FeatureNotFound")]
+ public static partial void FeatureNotFound(ILogger logger);
+
+ [LoggerMessage(2, LogLevel.Warning, "A request body size limit could not be applied. The IHttpRequestBodySizeFeature for the server is read-only.", EventName = "FeatureIsReadOnly")]
+ public static partial void FeatureIsReadOnly(ILogger logger);
+
+ [LoggerMessage(3, LogLevel.Debug, "The maximum request body size has been set to {RequestSize}.", EventName = "MaxRequestBodySizeSet")]
+ public static partial void MaxRequestBodySizeSet(ILogger logger, string requestSize);
+
+ [LoggerMessage(4, LogLevel.Debug, "Execution of filter {OverriddenFilter} is preempted by filter {OverridingFilter} which is the most effective filter implementing policy {FilterPolicy}.", EventName = "NotMostEffectiveFilter")]
+ public static partial void NotMostEffectiveFilter(ILogger logger, Type overriddenFilter, Type overridingFilter, Type filterPolicy);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Filters/ResponseCacheFilter.cs b/src/Mvc/Mvc.Core/src/Filters/ResponseCacheFilter.cs
index ee66600683c7..fa892a91756f 100644
--- a/src/Mvc/Mvc.Core/src/Filters/ResponseCacheFilter.cs
+++ b/src/Mvc/Mvc.Core/src/Filters/ResponseCacheFilter.cs
@@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters;
///
/// An which sets the appropriate headers related to response caching.
///
-internal class ResponseCacheFilter : IActionFilter, IResponseCacheFilter
+internal partial class ResponseCacheFilter : IActionFilter, IResponseCacheFilter
{
private readonly ResponseCacheFilterExecutor _executor;
private readonly ILogger _logger;
@@ -91,7 +91,7 @@ public void OnActionExecuting(ActionExecutingContext context)
var effectivePolicy = context.FindEffectivePolicy();
if (effectivePolicy != null && effectivePolicy != this)
{
- _logger.NotMostEffectiveFilter(GetType(), effectivePolicy.GetType(), typeof(IResponseCacheFilter));
+ Log.NotMostEffectiveFilter(_logger, GetType(), effectivePolicy.GetType(), typeof(IResponseCacheFilter));
return;
}
@@ -102,4 +102,10 @@ public void OnActionExecuting(ActionExecutingContext context)
public void OnActionExecuted(ActionExecutedContext context)
{
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(4, LogLevel.Debug, "Execution of filter {OverriddenFilter} is preempted by filter {OverridingFilter} which is the most effective filter implementing policy {FilterPolicy}.", EventName = "NotMostEffectiveFilter")]
+ public static partial void NotMostEffectiveFilter(ILogger logger, Type overriddenFilter, Type overridingFilter, Type filterPolicy);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Formatters/FormatFilter.cs b/src/Mvc/Mvc.Core/src/Formatters/FormatFilter.cs
index f734745cb9b0..d0b74ccdc9f1 100644
--- a/src/Mvc/Mvc.Core/src/Formatters/FormatFilter.cs
+++ b/src/Mvc/Mvc.Core/src/Formatters/FormatFilter.cs
@@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters;
/// A filter that will use the format value in the route data or query string to set the content type on an
/// returned from an action.
///
-public class FormatFilter : IFormatFilter, IResourceFilter, IResultFilter
+public partial class FormatFilter : IFormatFilter, IResourceFilter, IResultFilter
{
private readonly MvcOptions _options;
private readonly ILogger _logger;
@@ -82,7 +82,7 @@ public void OnResourceExecuting(ResourceExecutingContext context)
var contentType = _options.FormatterMappings.GetMediaTypeMappingForFormat(format);
if (contentType == null)
{
- _logger.UnsupportedFormatFilterContentType(format);
+ Log.UnsupportedFormatFilterContentType(_logger, format);
// no contentType exists for the format, return 404
context.Result = new NotFoundResult();
@@ -100,7 +100,7 @@ public void OnResourceExecuting(ResourceExecutingContext context)
// Check if support is adequate for requested media type.
if (supportedMediaTypes.Count == 0)
{
- _logger.ActionDoesNotExplicitlySpecifyContentTypes();
+ Log.ActionDoesNotExplicitlySpecifyContentTypes(_logger);
return;
}
@@ -163,7 +163,7 @@ public void OnResultExecuting(ResultExecutingContext context)
if (objectResult.ContentTypes.Count == 1 ||
!string.IsNullOrEmpty(context.HttpContext.Response.ContentType))
{
- _logger.CannotApplyFormatFilterContentType(format);
+ Log.CannotApplyFormatFilterContentType(_logger, format);
return;
}
@@ -179,4 +179,16 @@ public void OnResultExecuting(ResultExecutingContext context)
public void OnResultExecuted(ResultExecutedContext context)
{
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Debug, "Could not find a media type for the format '{FormatFilterContentType}'.", EventName = "UnsupportedFormatFilterContentType")]
+ public static partial void UnsupportedFormatFilterContentType(ILogger logger, string formatFilterContentType);
+
+ [LoggerMessage(3, LogLevel.Debug, "Cannot apply content type '{FormatFilterContentType}' to the response as current action had explicitly set a preferred content type.", EventName = "CannotApplyFormatFilterContentType")]
+ public static partial void CannotApplyFormatFilterContentType(ILogger logger, string formatFilterContentType);
+
+ [LoggerMessage(5, LogLevel.Debug, "Current action does not explicitly specify any content types for the response.", EventName = "ActionDoesNotExplicitlySpecifyContentTypes")]
+ public static partial void ActionDoesNotExplicitlySpecifyContentTypes(ILogger logger);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/ActionSelector.cs b/src/Mvc/Mvc.Core/src/Infrastructure/ActionSelector.cs
index d06276cb2b60..002003c5d147 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/ActionSelector.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/ActionSelector.cs
@@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A default implementation.
///
-internal class ActionSelector : IActionSelector
+internal partial class ActionSelector : IActionSelector
{
private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider;
private readonly ActionConstraintCache _actionConstraintCache;
@@ -108,8 +108,7 @@ public IReadOnlyList SelectCandidates(RouteContext context)
var actionNames = string.Join(
Environment.NewLine,
finalMatches.Select(a => a.DisplayName));
-
- _logger.AmbiguousActions(actionNames);
+ Log.AmbiguousActions(_logger, actionNames);
var message = Resources.FormatDefaultActionSelector_AmbiguousActions(
Environment.NewLine,
@@ -216,7 +215,8 @@ public IReadOnlyList SelectCandidates(RouteContext context)
if (!constraint.Accept(constraintContext))
{
isMatch = false;
- _logger.ConstraintMismatch(
+ Log.ConstraintMismatch(
+ _logger,
candidate.Action.DisplayName,
candidate.Action.Id,
constraint);
@@ -256,4 +256,13 @@ public IReadOnlyList SelectCandidates(RouteContext context)
return EvaluateActionConstraintsCore(context, actionsWithoutConstraint, order);
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Error, "Request matched multiple actions resulting in ambiguity. Matching actions: {AmbiguousActions}", EventName = "AmbiguousActions")]
+ public static partial void AmbiguousActions(ILogger logger, string ambiguousActions);
+
+ [LoggerMessage(2, LogLevel.Debug, "Action '{ActionName}' with id '{ActionId}' did not match the constraint '{ActionConstraint}'", EventName = "ConstraintMismatch")]
+ public static partial void ConstraintMismatch(ILogger logger, string? actionName, string actionId, IActionConstraint actionConstraint);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/ContentResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/ContentResultExecutor.cs
index ae405d89db5a..5529cd232eb6 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/ContentResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/ContentResultExecutor.cs
@@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A that is responsible for
///
-public class ContentResultExecutor : IActionResultExecutor
+public partial class ContentResultExecutor : IActionResultExecutor
{
private const string DefaultContentType = "text/plain; charset=utf-8";
private readonly ILogger _logger;
@@ -60,7 +60,7 @@ public virtual async Task ExecuteAsync(ActionContext context, ContentResult resu
response.StatusCode = result.StatusCode.Value;
}
- _logger.ContentResultExecuting(resolvedContentType);
+ Log.ContentResultExecuting(_logger, resolvedContentType);
if (result.Content != null)
{
@@ -78,4 +78,10 @@ public virtual async Task ExecuteAsync(ActionContext context, ContentResult resu
}
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing ContentResult with HTTP Response ContentType of {ContentType}", EventName = "ContentResultExecuting")]
+ public static partial void ContentResultExecuting(ILogger logger, string contentType);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/DefaultOutputFormatterSelector.cs b/src/Mvc/Mvc.Core/src/Infrastructure/DefaultOutputFormatterSelector.cs
index 8377bb053081..fa3e1442d15c 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/DefaultOutputFormatterSelector.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/DefaultOutputFormatterSelector.cs
@@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// The default implementation of .
///
-public class DefaultOutputFormatterSelector : OutputFormatterSelector
+public partial class DefaultOutputFormatterSelector : OutputFormatterSelector
{
private static readonly Comparison _sortFunction = (left, right) =>
{
@@ -84,7 +84,7 @@ public DefaultOutputFormatterSelector(IOptions options, ILoggerFacto
}
}
- _logger.RegisteredOutputFormatters(formatters);
+ Log.RegisteredOutputFormatters(_logger, formatters);
var request = context.HttpContext.Request;
var acceptableMediaTypes = GetAcceptableMediaTypes(request);
@@ -95,7 +95,7 @@ public DefaultOutputFormatterSelector(IOptions options, ILoggerFacto
{
// There is either no Accept header value, or it contained */* and we
// are not currently respecting the 'browser accept header'.
- _logger.NoAcceptForNegotiation();
+ Log.NoAcceptForNegotiation(_logger);
selectFormatterWithoutRegardingAcceptHeader = true;
}
@@ -103,7 +103,7 @@ public DefaultOutputFormatterSelector(IOptions options, ILoggerFacto
{
if (contentTypes.Count == 0)
{
- _logger.SelectingOutputFormatterUsingAcceptHeader(acceptableMediaTypes);
+ Log.SelectingOutputFormatterUsingAcceptHeader(_logger, acceptableMediaTypes);
// Use whatever formatter can meet the client's request
selectedFormatter = SelectFormatterUsingSortedAcceptHeaders(
@@ -113,7 +113,7 @@ public DefaultOutputFormatterSelector(IOptions options, ILoggerFacto
}
else
{
- _logger.SelectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes(acceptableMediaTypes, contentTypes);
+ Log.SelectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes(_logger, acceptableMediaTypes, contentTypes);
// Verify that a content type from the context is compatible with the client's request
selectedFormatter = SelectFormatterUsingSortedAcceptHeadersAndContentTypes(
@@ -125,7 +125,7 @@ public DefaultOutputFormatterSelector(IOptions options, ILoggerFacto
if (selectedFormatter == null)
{
- _logger.NoFormatterFromNegotiation(acceptableMediaTypes);
+ Log.NoFormatterFromNegotiation(_logger, acceptableMediaTypes);
if (!_returnHttpNotAcceptable)
{
@@ -138,7 +138,7 @@ public DefaultOutputFormatterSelector(IOptions options, ILoggerFacto
{
if (contentTypes.Count == 0)
{
- _logger.SelectingOutputFormatterWithoutUsingContentTypes();
+ Log.SelectingOutputFormatterWithoutUsingContentTypes(_logger);
selectedFormatter = SelectFormatterNotUsingContentType(
context,
@@ -146,7 +146,7 @@ public DefaultOutputFormatterSelector(IOptions options, ILoggerFacto
}
else
{
- _logger.SelectingOutputFormatterUsingContentTypes(contentTypes);
+ Log.SelectingOutputFormatterUsingContentTypes(_logger, contentTypes);
selectedFormatter = SelectFormatterUsingAnyAcceptableContentType(
context,
@@ -186,7 +186,7 @@ private List GetAcceptableMediaTypes(HttpRequest re
OutputFormatterCanWriteContext formatterContext,
IList formatters)
{
- _logger.SelectFirstCanWriteFormatter();
+ Log.SelectFirstCanWriteFormatter(_logger);
foreach (var formatter in formatters)
{
@@ -296,4 +296,31 @@ private static void ValidateContentTypes(MediaTypeCollection contentTypes)
}
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(4, LogLevel.Debug, "No information found on request to perform content negotiation.", EventName = "NoAcceptForNegotiation")]
+ public static partial void NoAcceptForNegotiation(ILogger logger);
+
+ [LoggerMessage(5, LogLevel.Debug, "Could not find an output formatter based on content negotiation. Accepted types were ({AcceptTypes})", EventName = "NoFormatterFromNegotiation")]
+ public static partial void NoFormatterFromNegotiation(ILogger logger, IList acceptTypes);
+
+ [LoggerMessage(6, LogLevel.Debug, "Attempting to select an output formatter based on Accept header '{AcceptHeader}'.", EventName = "SelectingOutputFormatterUsingAcceptHeader")]
+ public static partial void SelectingOutputFormatterUsingAcceptHeader(ILogger logger, IEnumerable acceptHeader);
+
+ [LoggerMessage(7, LogLevel.Debug, "Attempting to select an output formatter based on Accept header '{AcceptHeader}' and explicitly specified content types '{ExplicitContentTypes}'. The content types in the accept header must be a subset of the explicitly set content types.", EventName = "SelectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes")]
+ public static partial void SelectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes(ILogger logger, IEnumerable acceptHeader, MediaTypeCollection explicitContentTypes);
+
+ [LoggerMessage(8, LogLevel.Debug, "Attempting to select an output formatter without using a content type as no explicit content types were specified for the response.", EventName = "SelectingOutputFormatterWithoutUsingContentTypes")]
+ public static partial void SelectingOutputFormatterWithoutUsingContentTypes(ILogger logger);
+
+ [LoggerMessage(9, LogLevel.Debug, "Attempting to select the first output formatter in the output formatters list which supports a content type from the explicitly specified content types '{ExplicitContentTypes}'.", EventName = "SelectingOutputFormatterUsingContentTypes")]
+ public static partial void SelectingOutputFormatterUsingContentTypes(ILogger logger, MediaTypeCollection explicitContentTypes);
+
+ [LoggerMessage(10, LogLevel.Debug, "Attempting to select the first formatter in the output formatters list which can write the result.", EventName = "SelectingFirstCanWriteFormatter")]
+ public static partial void SelectFirstCanWriteFormatter(ILogger logger);
+
+ [LoggerMessage(11, LogLevel.Debug, "List of registered output formatters, in the following order: {OutputFormatters}", EventName = "RegisteredOutputFormatters")]
+ public static partial void RegisteredOutputFormatters(ILogger logger, IEnumerable outputFormatters);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/FileContentResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/FileContentResultExecutor.cs
index 80cd5a124610..5449a4d98697 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/FileContentResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/FileContentResultExecutor.cs
@@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A
///
-public class FileContentResultExecutor : FileResultExecutorBase, IActionResultExecutor
+public partial class FileContentResultExecutor : FileResultExecutorBase, IActionResultExecutor
{
///
/// Intializes a new .
@@ -79,10 +79,16 @@ protected virtual Task WriteFileAsync(ActionContext context, FileContentResult r
if (range != null)
{
- Logger.WritingRangeToBody();
+ Log.WritingRangeToBody(Logger);
}
var fileContentStream = new MemoryStream(result.FileContents);
return WriteFileAsync(context.HttpContext, fileContentStream, range, rangeLength);
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(17, LogLevel.Debug, "Writing the requested range of bytes to the body...", EventName = "WritingRangeToBody")]
+ public static partial void WritingRangeToBody(ILogger logger);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/FileStreamResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/FileStreamResultExecutor.cs
index 3a4d3461a661..51b88f7f223b 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/FileStreamResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/FileStreamResultExecutor.cs
@@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// An for a file stream result.
///
-public class FileStreamResultExecutor : FileResultExecutorBase, IActionResultExecutor
+public partial class FileStreamResultExecutor : FileResultExecutorBase, IActionResultExecutor
{
///
/// Initializes a new .
@@ -92,9 +92,15 @@ protected virtual Task WriteFileAsync(
if (range != null)
{
- Logger.WritingRangeToBody();
+ Log.WritingRangeToBody(Logger);
}
return WriteFileAsync(context.HttpContext, result.FileStream, range, rangeLength);
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(17, LogLevel.Debug, "Writing the requested range of bytes to the body...", EventName = "WritingRangeToBody")]
+ public static partial void WritingRangeToBody(ILogger logger);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/LocalRedirectResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/LocalRedirectResultExecutor.cs
index 8b989406c8ea..51d386c6ef5f 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/LocalRedirectResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/LocalRedirectResultExecutor.cs
@@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A that handles .
///
-public class LocalRedirectResultExecutor : IActionResultExecutor
+public partial class LocalRedirectResultExecutor : IActionResultExecutor
{
private readonly ILogger _logger;
private readonly IUrlHelperFactory _urlHelperFactory;
@@ -61,7 +61,7 @@ public virtual Task ExecuteAsync(ActionContext context, LocalRedirectResult resu
}
var destinationUrl = urlHelper.Content(result.Url);
- _logger.LocalRedirectResultExecuting(destinationUrl);
+ Log.LocalRedirectResultExecuting(_logger, destinationUrl);
if (result.PreserveMethod)
{
@@ -76,4 +76,10 @@ public virtual Task ExecuteAsync(ActionContext context, LocalRedirectResult resu
return Task.CompletedTask;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing LocalRedirectResult, redirecting to {Destination}.", EventName = "LocalRedirectResultExecuting")]
+ public static partial void LocalRedirectResultExecuting(ILogger logger, string destination);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/PhysicalFileResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/PhysicalFileResultExecutor.cs
index ba8378dc3277..e377cb86f3dd 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/PhysicalFileResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/PhysicalFileResultExecutor.cs
@@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A for .
///
-public class PhysicalFileResultExecutor : FileResultExecutorBase, IActionResultExecutor
+public partial class PhysicalFileResultExecutor : FileResultExecutorBase, IActionResultExecutor
{
///
/// Initializes a new instance of .
@@ -97,7 +97,7 @@ internal static Task WriteFileAsyncInternal(
if (range != null)
{
- logger.WritingRangeToBody();
+ Log.WritingRangeToBody(logger);
}
if (range != null)
@@ -177,4 +177,10 @@ protected class FileMetadata
///
public DateTimeOffset LastModified { get; set; }
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(17, LogLevel.Debug, "Writing the requested range of bytes to the body...", EventName = "WritingRangeToBody")]
+ public static partial void WritingRangeToBody(ILogger logger);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/RedirectResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/RedirectResultExecutor.cs
index 997c1ea38b08..5cf974f9cc33 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/RedirectResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/RedirectResultExecutor.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.Extensions.Logging;
@@ -11,7 +10,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A for .
///
-public class RedirectResultExecutor : IActionResultExecutor
+public partial class RedirectResultExecutor : IActionResultExecutor
{
private readonly ILogger _logger;
private readonly IUrlHelperFactory _urlHelperFactory;
@@ -59,7 +58,7 @@ public virtual Task ExecuteAsync(ActionContext context, RedirectResult result)
destinationUrl = urlHelper.Content(result.Url);
}
- _logger.RedirectResultExecuting(destinationUrl);
+ Log.RedirectResultExecuting(_logger, destinationUrl);
if (result.PreserveMethod)
{
@@ -74,4 +73,10 @@ public virtual Task ExecuteAsync(ActionContext context, RedirectResult result)
return Task.CompletedTask;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing RedirectResult, redirecting to {Destination}.", EventName = "RedirectResultExecuting")]
+ public static partial void RedirectResultExecuting(ILogger logger, string destination);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToActionResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToActionResultExecutor.cs
index e16011a1680e..c32f97d18b89 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToActionResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToActionResultExecutor.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Routing;
@@ -12,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A for .
///
-public class RedirectToActionResultExecutor : IActionResultExecutor
+public partial class RedirectToActionResultExecutor : IActionResultExecutor
{
private readonly ILogger _logger;
private readonly IUrlHelperFactory _urlHelperFactory;
@@ -65,7 +64,7 @@ public virtual Task ExecuteAsync(ActionContext context, RedirectToActionResult r
throw new InvalidOperationException(Resources.NoRoutesMatched);
}
- _logger.RedirectToActionResultExecuting(destinationUrl);
+ Log.RedirectToActionResultExecuting(_logger, destinationUrl);
if (result.PreserveMethod)
{
@@ -80,4 +79,10 @@ public virtual Task ExecuteAsync(ActionContext context, RedirectToActionResult r
return Task.CompletedTask;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing RedirectResult, redirecting to {Destination}.", EventName = "RedirectToActionResultExecuting")]
+ public static partial void RedirectToActionResultExecuting(ILogger logger, string destination);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToPageResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToPageResultExecutor.cs
index 4fd7f89570ef..e90904d8b348 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToPageResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToPageResultExecutor.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Routing;
@@ -12,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A for .
///
-public class RedirectToPageResultExecutor : IActionResultExecutor
+public partial class RedirectToPageResultExecutor : IActionResultExecutor
{
private readonly ILogger _logger;
private readonly IUrlHelperFactory _urlHelperFactory;
@@ -65,7 +64,7 @@ public virtual Task ExecuteAsync(ActionContext context, RedirectToPageResult res
throw new InvalidOperationException(Resources.FormatNoRoutesMatchedForPage(result.PageName));
}
- _logger.RedirectToPageResultExecuting(result.PageName);
+ Log.RedirectToPageResultExecuting(_logger, result.PageName);
if (result.PreserveMethod)
{
@@ -80,4 +79,10 @@ public virtual Task ExecuteAsync(ActionContext context, RedirectToPageResult res
return Task.CompletedTask;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing RedirectToPageResult, redirecting to {Page}.", EventName = "RedirectToPageResultExecuting")]
+ public static partial void RedirectToPageResultExecuting(ILogger logger, string? page);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToRouteResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToRouteResultExecutor.cs
index e21e0144462f..7ce084d57e4b 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToRouteResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/RedirectToRouteResultExecutor.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Routing;
@@ -12,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A for .
///
-public class RedirectToRouteResultExecutor : IActionResultExecutor
+public partial class RedirectToRouteResultExecutor : IActionResultExecutor
{
private readonly ILogger _logger;
private readonly IUrlHelperFactory _urlHelperFactory;
@@ -54,7 +53,7 @@ public virtual Task ExecuteAsync(ActionContext context, RedirectToRouteResult re
throw new InvalidOperationException(Resources.NoRoutesMatched);
}
- _logger.RedirectToRouteResultExecuting(destinationUrl, result.RouteName);
+ Log.RedirectToRouteResultExecuting(_logger, destinationUrl, result.RouteName);
if (result.PreserveMethod)
{
@@ -69,4 +68,10 @@ public virtual Task ExecuteAsync(ActionContext context, RedirectToRouteResult re
return Task.CompletedTask;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing RedirectToRouteResult, redirecting to {Destination} from route {RouteName}.", EventName = "RedirectToRouteResultExecuting")]
+ public static partial void RedirectToRouteResultExecuting(ILogger logger, string destination, string? routeName);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/ResourceInvoker.cs b/src/Mvc/Mvc.Core/src/Infrastructure/ResourceInvoker.cs
index f0c437bd3079..ae30ee19f9b4 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/ResourceInvoker.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/ResourceInvoker.cs
@@ -11,7 +11,7 @@
namespace Microsoft.AspNetCore.Mvc.Infrastructure;
-internal abstract class ResourceInvoker
+internal abstract partial class ResourceInvoker
{
protected readonly DiagnosticListener _diagnosticListener;
protected readonly ILogger _logger;
@@ -272,7 +272,7 @@ static async Task Logged(ResourceInvoker invoker, IActionResult result)
var actionContext = invoker._actionContext;
invoker._diagnosticListener.BeforeActionResult(actionContext, result);
- invoker._logger.BeforeExecutingActionResult(result);
+ Log.BeforeExecutingActionResult(invoker._logger, result);
try
{
@@ -281,7 +281,7 @@ static async Task Logged(ResourceInvoker invoker, IActionResult result)
finally
{
invoker._diagnosticListener.AfterActionResult(actionContext, result);
- invoker._logger.AfterExecutingActionResult(result);
+ Log.AfterExecutingActionResult(invoker._logger, result);
}
}
}
@@ -411,8 +411,7 @@ private Task Next(ref State next, ref Scope scope, ref object? state, ref bool i
Debug.Assert(state != null);
Debug.Assert(_authorizationContext != null);
Debug.Assert(_authorizationContext.Result != null);
-
- _logger.AuthorizationFailure((IFilterMetadata)state);
+ Log.AuthorizationFailure(_logger, (IFilterMetadata)state);
// This is a short-circuit - execute relevant result filters + result and complete this invocation.
isCompleted = true;
@@ -596,8 +595,7 @@ private Task Next(ref State next, ref Scope scope, ref object? state, ref bool i
Debug.Assert(state != null);
Debug.Assert(_resourceExecutingContext != null);
Debug.Assert(_resourceExecutedContext != null);
-
- _logger.ResourceFilterShortCircuited((IFilterMetadata)state);
+ Log.ResourceFilterShortCircuited(_logger, (IFilterMetadata)state);
_result = _resourceExecutingContext.Result;
var task = InvokeAlwaysRunResultFilters();
@@ -1605,4 +1603,29 @@ private sealed class AuthorizationFilterContextSealed : AuthorizationFilterConte
{
public AuthorizationFilterContextSealed(ActionContext actionContext, IList filters) : base(actionContext, filters) { }
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(3, LogLevel.Information, "Authorization failed for the request at filter '{AuthorizationFilter}'.", EventName = "AuthorizationFailure")]
+ public static partial void AuthorizationFailure(ILogger logger, IFilterMetadata authorizationFilter);
+
+ [LoggerMessage(4, LogLevel.Debug, "Request was short circuited at resource filter '{ResourceFilter}'.", EventName = "ResourceFilterShortCircuit")]
+ public static partial void ResourceFilterShortCircuited(ILogger logger, IFilterMetadata resourceFilter);
+
+ [LoggerMessage(5, LogLevel.Trace, "Before executing action result {ActionResult}.", EventName = "BeforeExecutingActionResult")]
+ private static partial void BeforeExecutingActionResult(ILogger logger, Type actionResult);
+
+ public static void BeforeExecutingActionResult(ILogger logger, IActionResult actionResult)
+ {
+ BeforeExecutingActionResult(logger, actionResult.GetType());
+ }
+
+ [LoggerMessage(6, LogLevel.Trace, "After executing action result {ActionResult}.", EventName = "AfterExecutingActionResult")]
+ private static partial void AfterExecutingActionResult(ILogger logger, Type actionResult);
+
+ public static void AfterExecutingActionResult(ILogger logger, IActionResult actionResult)
+ {
+ AfterExecutingActionResult(logger, actionResult.GetType());
+ }
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/VirtualFileResultExecutor.cs b/src/Mvc/Mvc.Core/src/Infrastructure/VirtualFileResultExecutor.cs
index 89d6a17c7439..59c8a0976943 100644
--- a/src/Mvc/Mvc.Core/src/Infrastructure/VirtualFileResultExecutor.cs
+++ b/src/Mvc/Mvc.Core/src/Infrastructure/VirtualFileResultExecutor.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Core;
@@ -14,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure;
///
/// A for .
///
-public class VirtualFileResultExecutor : FileResultExecutorBase, IActionResultExecutor
+public partial class VirtualFileResultExecutor : FileResultExecutorBase, IActionResultExecutor
{
private readonly IWebHostEnvironment _hostingEnvironment;
@@ -105,7 +104,7 @@ internal static Task WriteFileAsyncInternal(
if (range != null)
{
- logger.WritingRangeToBody();
+ Log.WritingRangeToBody(logger);
}
if (range != null)
@@ -159,4 +158,10 @@ protected virtual Stream GetFileStream(IFileInfo fileInfo)
{
return fileInfo.CreateReadStream();
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(17, LogLevel.Debug, "Writing the requested range of bytes to the body...", EventName = "WritingRangeToBody")]
+ public static partial void WritingRangeToBody(ILogger logger);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/FormFileModelBinder.cs b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/FormFileModelBinder.cs
index 04776ef5da4e..ce6596db8104 100644
--- a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/FormFileModelBinder.cs
+++ b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/FormFileModelBinder.cs
@@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
///
/// implementation to bind posted files to .
///
-public class FormFileModelBinder : IModelBinder
+public partial class FormFileModelBinder : IModelBinder
{
private readonly ILogger _logger;
@@ -164,7 +164,7 @@ private async Task GetFormFilesAsync(
if (postedFiles.Count == 0)
{
- _logger.NoFilesFoundInRequest();
+ Log.NoFilesFoundInRequest(_logger);
}
}
else
@@ -211,4 +211,10 @@ public IReadOnlyList GetFiles(string name)
return files;
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(21, LogLevel.Debug, "No files found in the request to bind the model to.", EventName = "NoFilesFoundInRequest")]
+ public static partial void NoFilesFoundInRequest(ILogger logger);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/HeaderModelBinderProvider.cs b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/HeaderModelBinderProvider.cs
index 724efb810538..fd29db9b64c4 100644
--- a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/HeaderModelBinderProvider.cs
+++ b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/HeaderModelBinderProvider.cs
@@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
///
/// An for binding header values.
///
-public class HeaderModelBinderProvider : IModelBinderProvider
+public partial class HeaderModelBinderProvider : IModelBinderProvider
{
///
public IModelBinder? GetBinder(ModelBinderProviderContext context)
@@ -34,7 +34,7 @@ public class HeaderModelBinderProvider : IModelBinderProvider
if (!IsSimpleType(modelMetadata))
{
- logger.CannotCreateHeaderModelBinder(modelMetadata.ModelType);
+ Log.CannotCreateHeaderModelBinder(logger, modelMetadata.ModelType);
return null;
}
@@ -64,4 +64,10 @@ private static bool IsSimpleType(ModelMetadata modelMetadata)
var metadata = modelMetadata.ElementMetadata ?? modelMetadata;
return !metadata.IsComplexType;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(20, LogLevel.Debug, "Could not create a binder for type '{ModelType}' as this binder only supports simple types (like string, int, bool, enum) or a collection of simple types.", EventName = "CannotCreateHeaderModelBinder")]
+ public static partial void CannotCreateHeaderModelBinder(ILogger logger, Type modelType);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/ModelBinderFactory.cs b/src/Mvc/Mvc.Core/src/ModelBinding/ModelBinderFactory.cs
index 3a96afac1417..30754d9dcff4 100644
--- a/src/Mvc/Mvc.Core/src/ModelBinding/ModelBinderFactory.cs
+++ b/src/Mvc/Mvc.Core/src/ModelBinding/ModelBinderFactory.cs
@@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding;
///
/// A factory for instances.
///
-public class ModelBinderFactory : IModelBinderFactory
+public partial class ModelBinderFactory : IModelBinderFactory
{
private readonly IModelMetadataProvider _metadataProvider;
private readonly IModelBinderProvider[] _providers;
@@ -44,7 +44,7 @@ public ModelBinderFactory(
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- logger.RegisteredModelBinderProviders(_providers);
+ Log.RegisteredModelBinderProviders(logger, _providers);
}
///
@@ -329,4 +329,10 @@ public override string ToString()
}
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(12, LogLevel.Debug, "Registered model binder providers, in the following order: {ModelBinderProviders}", EventName = "RegisteredModelBinderProviders")]
+ public static partial void RegisteredModelBinderProviders(ILogger logger, IModelBinderProvider[] modelBinderProviders);
+ }
}
diff --git a/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs b/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs
index 53ecf1a827f7..7fdff5b34705 100644
--- a/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs
+++ b/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs
@@ -7,10 +7,8 @@
using System.Globalization;
using System.Linq;
using System.Reflection;
-using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Mvc.Abstractions;
-using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
@@ -39,9 +37,6 @@ internal static partial class MvcCoreLoggerExtensions
private static readonly Action _pageExecuted;
private static readonly Action _challengeResultExecuting;
-
- private static readonly Action _contentResultExecuting;
-
private static readonly Action _actionMethodExecuting;
private static readonly Action _actionMethodExecutingWithArguments;
private static readonly Action _actionMethodExecuted;
@@ -49,64 +44,25 @@ internal static partial class MvcCoreLoggerExtensions
private static readonly Action _logFilterExecutionPlan;
private static readonly Action _beforeExecutingMethodOnFilter;
private static readonly Action _afterExecutingMethodOnFilter;
- private static readonly Action _beforeExecutingActionResult;
- private static readonly Action _afterExecutingActionResult;
-
- private static readonly Action _ambiguousActions;
- private static readonly Action _constraintMismatch;
-
private static readonly Action _executingFileResult;
private static readonly Action _executingFileResultWithNoFileName;
- private static readonly Action _notEnabledForRangeProcessing;
- private static readonly Action _writingRangeToBody;
- private static readonly Action _authorizationFailure;
- private static readonly Action _resourceFilterShortCircuit;
private static readonly Action _resultFilterShortCircuit;
private static readonly Action _actionFilterShortCircuit;
private static readonly Action _exceptionFilterShortCircuit;
private static readonly Action _forbidResultExecuting;
- private static readonly Action _signInResultExecuting;
private static readonly Action _signOutResultExecuting;
-
- private static readonly Action _httpStatusCodeResultExecuting;
-
- private static readonly Action _localRedirectResultExecuting;
-
private static readonly Action _objectResultExecuting;
private static readonly Action, Exception> _noFormatter;
private static readonly Action _formatterSelected;
- private static readonly Action _skippedContentNegotiation;
- private static readonly Action _noAcceptForNegotiation;
- private static readonly Action, Exception> _noFormatterFromNegotiation;
-
private static readonly Action _inputFormatterSelected;
private static readonly Action _inputFormatterRejected;
private static readonly Action _noInputFormatterSelected;
private static readonly Action _removeFromBodyAttribute;
-
- private static readonly Action _redirectResultExecuting;
-
- private static readonly Action _redirectToActionResultExecuting;
-
- private static readonly Action _redirectToRouteResultExecuting;
-
private static readonly Action _noActionsMatched;
-
- private static readonly Action _redirectToPageResultExecuting;
-
- private static readonly Action _featureNotFound;
- private static readonly Action _featureIsReadOnly;
- private static readonly Action _maxRequestBodySizeSet;
- private static readonly Action _requestBodySizeLimitDisabled;
-
- private static readonly Action _cannotApplyRequestFormLimits;
- private static readonly Action _appliedRequestFormLimits;
-
private static readonly Action _modelStateInvalidFilterExecuting;
private static readonly Action _inferredParameterSource;
- private static readonly Action _registeredModelBinderProviders;
private static readonly Action _foundNoValueForPropertyInRequest;
private static readonly Action _foundNoValueForParameterInRequest;
private static readonly Action _foundNoValueInRequest;
@@ -115,9 +71,7 @@ internal static partial class MvcCoreLoggerExtensions
private static readonly Action _noPublicSettableProperties;
private static readonly Action _cannotBindToComplexType;
private static readonly Action _cannotBindToFilesCollectionDueToUnsupportedContentType;
- private static readonly Action _cannotCreateHeaderModelBinder;
private static readonly Action _cannotCreateHeaderModelBinderCompatVersion_2_0;
- private static readonly Action _noFilesFoundInRequest;
private static readonly Action _noNonIndexBasedFormatFoundForCollection;
private static readonly Action _attemptingToBindCollectionUsingIndices;
private static readonly Action _attemptingToBindCollectionOfKeyValuePair;
@@ -136,22 +90,10 @@ internal static partial class MvcCoreLoggerExtensions
private static readonly Action _doneAttemptingToValidateProperty;
private static readonly Action _attemptingToValidateParameter;
private static readonly Action _doneAttemptingToValidateParameter;
- private static readonly Action _unsupportedFormatFilterContentType;
private static readonly Action _actionDoesNotSupportFormatFilterContentType;
- private static readonly Action _cannotApplyFormatFilterContentType;
- private static readonly Action _actionDoesNotExplicitlySpecifyContentTypes;
- private static readonly Action, Exception> _selectingOutputFormatterUsingAcceptHeader;
- private static readonly Action _ifMatchPreconditionFailed;
private static readonly Action _ifUnmodifiedSincePreconditionFailed;
private static readonly Action _ifRangeLastModifiedPreconditionFailed;
private static readonly Action _ifRangeETagPreconditionFailed;
- private static readonly Action, MediaTypeCollection, Exception> _selectingOutputFormatterUsingAcceptHeaderAndExplicitContentTypes;
- private static readonly Action _selectingOutputFormatterWithoutUsingContentTypes;
- private static readonly Action _selectingOutputFormatterUsingContentTypes;
- private static readonly Action _selectingFirstCanWriteFormatter;
- private static readonly Action _notMostEffectiveFilter;
- private static readonly Action, Exception> _registeredOutputFormatters;
-
private static readonly Action _transformingClientError;
static MvcCoreLoggerExtensions()
@@ -204,12 +146,6 @@ static MvcCoreLoggerExtensions()
new EventId(1, "ChallengeResultExecuting"),
"Executing ChallengeResult with authentication schemes ({Schemes}).",
SkipEnabledCheckLogOptions);
-
- _contentResultExecuting = LoggerMessage.Define(
- LogLevel.Information,
- new EventId(1, "ContentResultExecuting"),
- "Executing ContentResult with HTTP Response ContentType of {ContentType}");
-
_actionMethodExecuting = LoggerMessage.Define(
LogLevel.Information,
new EventId(1, "ActionMethodExecuting"),
@@ -243,27 +179,6 @@ static MvcCoreLoggerExtensions()
LogLevel.Trace,
new EventId(3, "AfterExecutingMethodOnFilter"),
"{FilterType}: After executing {Method} on filter {Filter}.");
-
- _beforeExecutingActionResult = LoggerMessage.Define(
- LogLevel.Trace,
- new EventId(4, "BeforeExecutingActionResult"),
- "Before executing action result {ActionResult}.");
-
- _afterExecutingActionResult = LoggerMessage.Define(
- LogLevel.Trace,
- new EventId(5, "AfterExecutingActionResult"),
- "After executing action result {ActionResult}.");
-
- _ambiguousActions = LoggerMessage.Define(
- LogLevel.Error,
- new EventId(1, "AmbiguousActions"),
- "Request matched multiple actions resulting in ambiguity. Matching actions: {AmbiguousActions}");
-
- _constraintMismatch = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(2, "ConstraintMismatch"),
- "Action '{ActionName}' with id '{ActionId}' did not match the constraint '{ActionConstraint}'");
-
_executingFileResult = LoggerMessage.Define(
LogLevel.Information,
new EventId(1, "ExecutingFileResult"),
@@ -275,17 +190,6 @@ static MvcCoreLoggerExtensions()
new EventId(2, "ExecutingFileResultWithNoFileName"),
"Executing {FileResultType}, sending file with download name '{FileDownloadName}' ...",
SkipEnabledCheckLogOptions);
-
- _authorizationFailure = LoggerMessage.Define
-public class XmlSerializerOutputFormatter : TextOutputFormatter
+public partial class XmlSerializerOutputFormatter : TextOutputFormatter
{
private readonly ConcurrentDictionary _serializerCache = new ConcurrentDictionary();
private readonly ILogger _logger;
@@ -145,7 +145,7 @@ protected override bool CanWriteType(Type? type)
}
catch (Exception ex)
{
- _logger.FailedToCreateXmlSerializer(type.FullName!, ex);
+ Log.FailedToCreateXmlSerializer(_logger, type.FullName!, ex);
// We do not surface the caught exception because if CanWriteResult returns
// false, then this Formatter is not picked up at all.
@@ -316,22 +316,20 @@ protected virtual XmlSerializer GetCachedSerializer(Type type)
return (XmlSerializer)serializer!;
}
- private static class Log
+ private static partial class Log
{
- private static readonly LogDefineOptions SkipEnabledCheckLogOptions = new() { SkipEnabledCheck = true };
-
- private static readonly Action _bufferingAsyncEnumerable = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(1, "BufferingAsyncEnumerable"),
- "Buffering IAsyncEnumerable instance of type '{Type}'.",
- SkipEnabledCheckLogOptions);
+ [LoggerMessage(1, LogLevel.Debug, "Buffering IAsyncEnumerable instance of type '{Type}'.", EventName = "BufferingAsyncEnumerable", SkipEnabledCheck = true)]
+ private static partial void BufferingAsyncEnumerable(ILogger logger, string type);
public static void BufferingAsyncEnumerable(ILogger logger, object asyncEnumerable)
{
if (logger.IsEnabled(LogLevel.Debug))
{
- _bufferingAsyncEnumerable(logger, asyncEnumerable.GetType().FullName!, null);
+ BufferingAsyncEnumerable(logger, asyncEnumerable.GetType().FullName!);
}
}
+
+ [LoggerMessage(2, LogLevel.Warning, "An error occurred while trying to create an XmlSerializer for the type '{Type}'.", EventName = "FailedToCreateXmlSerializer")]
+ public static partial void FailedToCreateXmlSerializer(ILogger logger, string type, Exception exception);
}
}
diff --git a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs
index 04038eb92759..61c0c03b0a12 100644
--- a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs
+++ b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs
@@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters;
///
/// A for JSON content.
///
-public class NewtonsoftJsonInputFormatter : TextInputFormatter, IInputFormatterExceptionPolicy
+public partial class NewtonsoftJsonInputFormatter : TextInputFormatter, IInputFormatterExceptionPolicy
{
private readonly IArrayPool _charPool;
private readonly ILogger _logger;
@@ -329,8 +329,7 @@ void ErrorHandler(object? sender, Newtonsoft.Json.Serialization.ErrorEventArgs e
var metadata = GetPathMetadata(context.Metadata, path);
var modelStateException = WrapExceptionForModelState(exception);
context.ModelState.TryAddModelError(key, modelStateException, metadata);
-
- _logger.JsonInputException(exception);
+ Log.JsonInputException(_logger, exception);
// Error must always be marked as handled
// Failure to do so can cause the exception to be rethrown at every recursive level and
@@ -453,4 +452,10 @@ private Exception WrapExceptionForModelState(Exception exception)
// Not a known exception type, so we're not going to assume that it's safe.
return exception;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Debug, "JSON input formatter threw an exception.", EventName = "JsonInputException")]
+ public static partial void JsonInputException(ILogger logger, Exception exception);
+ }
}
diff --git a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonLoggerExtensions.cs b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonLoggerExtensions.cs
deleted file mode 100644
index 023f54047e74..000000000000
--- a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonLoggerExtensions.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Microsoft.Extensions.Logging;
-
-namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson;
-
-internal static class NewtonsoftJsonLoggerExtensions
-{
- private static readonly Action _jsonInputFormatterException;
-
- static NewtonsoftJsonLoggerExtensions()
- {
- _jsonInputFormatterException = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(1, "JsonInputException"),
- "JSON input formatter threw an exception.");
- }
-
- public static void JsonInputException(this ILogger logger, Exception exception)
- {
- _jsonInputFormatterException(logger, exception);
- }
-}
diff --git a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs
index 777689c568c8..a6f8703ce498 100644
--- a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs
+++ b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs
@@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters;
///
/// A for JSON content.
///
-public class NewtonsoftJsonOutputFormatter : TextOutputFormatter
+public partial class NewtonsoftJsonOutputFormatter : TextOutputFormatter
{
private readonly IArrayPool _charPool;
private readonly MvcOptions _mvcOptions;
@@ -245,21 +245,16 @@ private static JsonSerializerSettings ShallowCopy(JsonSerializerSettings setting
return copiedSettings;
}
- private static class Log
+ private static partial class Log
{
- private static readonly LogDefineOptions SkipEnabledCheckLogOptions = new() { SkipEnabledCheck = true };
-
- private static readonly Action _bufferingAsyncEnumerable = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(1, "BufferingAsyncEnumerable"),
- "Buffering IAsyncEnumerable instance of type '{Type}'.",
- SkipEnabledCheckLogOptions);
+ [LoggerMessage(1, LogLevel.Debug, "Buffering IAsyncEnumerable instance of type '{Type}'.", EventName = "BufferingAsyncEnumerable", SkipEnabledCheck = true)]
+ private static partial void BufferingAsyncEnumerable(ILogger logger, string? type);
public static void BufferingAsyncEnumerable(ILogger logger, object asyncEnumerable)
{
if (logger.IsEnabled(LogLevel.Debug))
{
- _bufferingAsyncEnumerable(logger, asyncEnumerable.GetType().FullName, null);
+ BufferingAsyncEnumerable(logger, asyncEnumerable.GetType().FullName);
}
}
}
diff --git a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonResultExecutor.cs b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonResultExecutor.cs
index 4f5177946212..179e382b26b9 100644
--- a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonResultExecutor.cs
+++ b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonResultExecutor.cs
@@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson;
///
/// Executes a to write to the response.
///
-internal class NewtonsoftJsonResultExecutor : IActionResultExecutor
+internal partial class NewtonsoftJsonResultExecutor : IActionResultExecutor
{
private static readonly string DefaultContentType = new MediaTypeHeaderValue("application/json")
{
@@ -185,36 +185,28 @@ private JsonSerializerSettings GetSerializerSettings(JsonResult result)
}
}
- private static class Log
+ private static partial class Log
{
- private static readonly LogDefineOptions SkipEnabledCheckLogOptions = new() { SkipEnabledCheck = true };
+ [LoggerMessage(1, LogLevel.Debug, "Buffering IAsyncEnumerable instance of type '{Type}'.", EventName = "BufferingAsyncEnumerable", SkipEnabledCheck = true)]
+ private static partial void BufferingAsyncEnumerable(ILogger logger, string? type);
- private static readonly Action _jsonResultExecuting = LoggerMessage.Define(
- LogLevel.Information,
- new EventId(1, "JsonResultExecuting"),
- "Executing JsonResult, writing value of type '{Type}'.",
- SkipEnabledCheckLogOptions);
-
- private static readonly Action _bufferingAsyncEnumerable = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(1, "BufferingAsyncEnumerable"),
- "Buffering IAsyncEnumerable instance of type '{Type}'.",
- SkipEnabledCheckLogOptions);
-
- public static void JsonResultExecuting(ILogger logger, object? value)
+ public static void BufferingAsyncEnumerable(ILogger logger, object asyncEnumerable)
{
- if (logger.IsEnabled(LogLevel.Information))
+ if (logger.IsEnabled(LogLevel.Debug))
{
- var type = value == null ? "null" : value.GetType().FullName;
- _jsonResultExecuting(logger, type, null);
+ BufferingAsyncEnumerable(logger, asyncEnumerable.GetType().FullName);
}
}
- public static void BufferingAsyncEnumerable(ILogger logger, object asyncEnumerable)
+ [LoggerMessage(2, LogLevel.Information, "Executing JsonResult, writing value of type '{Type}'.", EventName = "JsonResultExecuting", SkipEnabledCheck = true)]
+ private static partial void JsonResultExecuting(ILogger logger, string? type);
+
+ public static void JsonResultExecuting(ILogger logger, object? value)
{
- if (logger.IsEnabled(LogLevel.Debug))
+ if (logger.IsEnabled(LogLevel.Information))
{
- _bufferingAsyncEnumerable(logger, asyncEnumerable.GetType().FullName, null);
+ var type = value == null ? "null" : value.GetType().FullName;
+ JsonResultExecuting(logger, type);
}
}
}
diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/PageDirectiveFeature.cs b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/PageDirectiveFeature.cs
index e897047f20aa..08ce30d049e6 100644
--- a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/PageDirectiveFeature.cs
+++ b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/PageDirectiveFeature.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language;
@@ -10,7 +11,7 @@
namespace Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation;
-internal static class PageDirectiveFeature
+internal static partial class PageDirectiveFeature
{
private static readonly RazorProjectEngine PageDirectiveEngine = RazorProjectEngine.Create(RazorConfiguration.Default, new EmptyRazorProjectFileSystem(), builder =>
{
@@ -42,7 +43,7 @@ public static bool TryGetPageDirective(ILogger logger, RazorProjectItem projectI
{
if (pageDirective.DirectiveNode is MalformedDirectiveIntermediateNode malformedNode)
{
- logger.MalformedPageDirective(projectItem.FilePath, malformedNode.Diagnostics);
+ Log.MalformedPageDirective(logger, projectItem.FilePath, malformedNode.Diagnostics);
}
template = pageDirective.RouteTemplate;
@@ -114,4 +115,24 @@ public NotFoundProjectItem(string basePath, string path, string? fileKind)
public override Stream Read() => throw new NotSupportedException();
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(104, LogLevel.Warning, "The page directive at '{FilePath}' is malformed. Please fix the following issues: {Diagnostics}", EventName = "MalformedPageDirective", SkipEnabledCheck = true)]
+ private static partial void MalformedPageDirective(ILogger logger, string filePath, string[] diagnostics);
+
+ public static void MalformedPageDirective(ILogger logger, string filePath, IList diagnostics)
+ {
+ if (logger.IsEnabled(LogLevel.Warning))
+ {
+ var messages = new string[diagnostics.Count];
+ for (var i = 0; i < diagnostics.Count; i++)
+ {
+ messages[i] = diagnostics[i].GetMessage(CultureInfo.CurrentCulture);
+ }
+
+ MalformedPageDirective(logger, filePath, messages);
+ }
+ }
+ }
}
diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RazorRuntimeCompilationLoggerExtensions.cs b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RazorRuntimeCompilationLoggerExtensions.cs
deleted file mode 100644
index 0d9555f5dade..000000000000
--- a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RazorRuntimeCompilationLoggerExtensions.cs
+++ /dev/null
@@ -1,180 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.Globalization;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.Extensions.Logging;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation;
-
-internal static class MvcRazorLoggerExtensions
-{
- private static readonly double TimestampToTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
-
- private static readonly Action _generatedCodeToAssemblyCompilationStart;
- private static readonly Action _generatedCodeToAssemblyCompilationEnd;
- private static readonly Action _malformedPageDirective;
- private static readonly Action _viewCompilerLocatedCompiledView;
- private static readonly Action _viewCompilerNoCompiledViewsFound;
- private static readonly Action _viewCompilerLocatedCompiledViewForPath;
- private static readonly Action _viewCompilerRecompilingCompiledView;
- private static readonly Action _viewCompilerCouldNotFindFileToCompileForPath;
- private static readonly Action _viewCompilerFoundFileToCompileForPath;
- private static readonly Action _viewCompilerInvalidatingCompiledFile;
-
- private static readonly Action _viewLookupCacheMiss;
- private static readonly Action _viewLookupCacheHit;
- private static readonly Action _precompiledViewFound;
-
- private static readonly LogDefineOptions SkipEnabledCheckLogOptions = new() { SkipEnabledCheck = true };
-
- static MvcRazorLoggerExtensions()
- {
- _viewCompilerLocatedCompiledView = LoggerMessage.Define(
- LogLevel.Debug,
- 3,
- "Initializing Razor view compiler with compiled view: '{ViewName}'.");
-
- _viewCompilerNoCompiledViewsFound = LoggerMessage.Define(
- LogLevel.Debug,
- 4,
- "Initializing Razor view compiler with no compiled views.");
-
- _viewCompilerLocatedCompiledViewForPath = LoggerMessage.Define(
- LogLevel.Trace,
- 5,
- "Located compiled view for view at path '{Path}'.");
-
- _viewCompilerLocatedCompiledViewForPath = LoggerMessage.Define(
- LogLevel.Trace,
- 5,
- "Located compiled view for view at path '{Path}'.");
-
- _viewCompilerRecompilingCompiledView = LoggerMessage.Define(
- LogLevel.Trace,
- 6,
- "Invalidating compiled view for view at path '{Path}'.");
-
- _viewCompilerCouldNotFindFileToCompileForPath = LoggerMessage.Define(
- LogLevel.Trace,
- 7,
- "Could not find a file for view at path '{Path}'.");
-
- _viewCompilerFoundFileToCompileForPath = LoggerMessage.Define(
- LogLevel.Trace,
- 8,
- "Found file at path '{Path}'.");
-
- _viewCompilerInvalidatingCompiledFile = LoggerMessage.Define(
- LogLevel.Trace,
- 9,
- "Invalidating compiled view at path '{Path}' with a file since the checksum did not match.");
-
- _viewLookupCacheMiss = LoggerMessage.Define(
- LogLevel.Debug,
- 1,
- "View lookup cache miss for view '{ViewName}' in controller '{ControllerName}'.");
-
- _viewLookupCacheHit = LoggerMessage.Define(
- LogLevel.Debug,
- 2,
- "View lookup cache hit for view '{ViewName}' in controller '{ControllerName}'.");
-
- _precompiledViewFound = LoggerMessage.Define(
- LogLevel.Debug,
- 3,
- "Using precompiled view for '{RelativePath}'.");
-
- _generatedCodeToAssemblyCompilationStart = LoggerMessage.Define(
- LogLevel.Debug,
- 1,
- "Compilation of the generated code for the Razor file at '{FilePath}' started.");
-
- _generatedCodeToAssemblyCompilationEnd = LoggerMessage.Define(
- LogLevel.Debug,
- 2,
- "Compilation of the generated code for the Razor file at '{FilePath}' completed in {ElapsedMilliseconds}ms.");
-
- _malformedPageDirective = LoggerMessage.Define(
- LogLevel.Warning,
- new EventId(104, "MalformedPageDirective"),
- "The page directive at '{FilePath}' is malformed. Please fix the following issues: {Diagnostics}",
- SkipEnabledCheckLogOptions);
- }
-
- public static void ViewCompilerLocatedCompiledView(this ILogger logger, string view)
- {
- _viewCompilerLocatedCompiledView(logger, view, null);
- }
-
- public static void ViewCompilerNoCompiledViewsFound(this ILogger logger)
- {
- _viewCompilerNoCompiledViewsFound(logger, null);
- }
-
- public static void ViewCompilerLocatedCompiledViewForPath(this ILogger logger, string path)
- {
- _viewCompilerLocatedCompiledViewForPath(logger, path, null);
- }
-
- public static void ViewCompilerCouldNotFindFileAtPath(this ILogger logger, string path)
- {
- _viewCompilerCouldNotFindFileToCompileForPath(logger, path, null);
- }
-
- public static void ViewCompilerFoundFileToCompile(this ILogger logger, string path)
- {
- _viewCompilerFoundFileToCompileForPath(logger, path, null);
- }
-
- public static void ViewCompilerInvalidingCompiledFile(this ILogger logger, string path)
- {
- _viewCompilerInvalidatingCompiledFile(logger, path, null);
- }
-
- public static void ViewLookupCacheMiss(this ILogger logger, string viewName, string controllerName)
- {
- _viewLookupCacheMiss(logger, viewName, controllerName, null);
- }
-
- public static void ViewLookupCacheHit(this ILogger logger, string viewName, string controllerName)
- {
- _viewLookupCacheHit(logger, viewName, controllerName, null);
- }
-
- public static void PrecompiledViewFound(this ILogger logger, string relativePath)
- {
- _precompiledViewFound(logger, relativePath, null);
- }
-
- public static void GeneratedCodeToAssemblyCompilationStart(this ILogger logger, string filePath)
- {
- _generatedCodeToAssemblyCompilationStart(logger, filePath, null);
- }
-
- public static void GeneratedCodeToAssemblyCompilationEnd(this ILogger logger, string filePath, long startTimestamp)
- {
- // Don't log if logging wasn't enabled at start of request as time will be wildly wrong.
- if (startTimestamp != 0)
- {
- var currentTimestamp = Stopwatch.GetTimestamp();
- var elapsed = new TimeSpan((long)(TimestampToTicks * (currentTimestamp - startTimestamp)));
- _generatedCodeToAssemblyCompilationEnd(logger, filePath, elapsed.TotalMilliseconds, null);
- }
- }
-
- public static void MalformedPageDirective(this ILogger logger, string filePath, IList diagnostics)
- {
- if (logger.IsEnabled(LogLevel.Warning))
- {
- var messages = new string[diagnostics.Count];
- for (var i = 0; i < diagnostics.Count; i++)
- {
- messages[i] = diagnostics[i].GetMessage(CultureInfo.CurrentCulture);
- }
-
- _malformedPageDirective(logger, filePath, messages, null);
- }
- }
-}
diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RuntimeViewCompiler.cs b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RuntimeViewCompiler.cs
index 31914c918463..c075ff7fc54a 100644
--- a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RuntimeViewCompiler.cs
+++ b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RuntimeViewCompiler.cs
@@ -19,7 +19,7 @@
namespace Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation;
-internal class RuntimeViewCompiler : IViewCompiler
+internal partial class RuntimeViewCompiler : IViewCompiler
{
private readonly object _cacheLock = new object();
private readonly Dictionary _precompiledViews;
@@ -84,7 +84,7 @@ public RuntimeViewCompiler(
foreach (var precompiledView in precompiledViews)
{
- logger.ViewCompilerLocatedCompiledView(precompiledView.RelativePath);
+ Log.ViewCompilerLocatedCompiledView(_logger, precompiledView.RelativePath);
if (!_precompiledViews.ContainsKey(precompiledView.RelativePath))
{
@@ -96,7 +96,7 @@ public RuntimeViewCompiler(
if (_precompiledViews.Count == 0)
{
- logger.ViewCompilerNoCompiledViewsFound();
+ Log.ViewCompilerNoCompiledViewsFound(_logger);
}
}
@@ -144,7 +144,7 @@ private Task OnCacheMiss(string normalizedPath)
if (_precompiledViews.TryGetValue(normalizedPath, out var precompiledView))
{
- _logger.ViewCompilerLocatedCompiledViewForPath(normalizedPath);
+ Log.ViewCompilerLocatedCompiledViewForPath(_logger, normalizedPath);
item = CreatePrecompiledWorkItem(normalizedPath, precompiledView);
}
else
@@ -192,7 +192,7 @@ private Task OnCacheMiss(string normalizedPath)
return taskSource.Task;
}
- _logger.ViewCompilerInvalidingCompiledFile(item.NormalizedPath);
+ Log.ViewCompilerInvalidatingCompiledFile(_logger, item.NormalizedPath);
try
{
var descriptor = CompileAndEmit(normalizedPath);
@@ -264,7 +264,7 @@ private ViewCompilerWorkItem CreateRuntimeCompilationWorkItem(string normalizedP
var projectItem = _projectEngine.FileSystem.GetItem(normalizedPath, fileKind: null);
if (!projectItem.Exists)
{
- _logger.ViewCompilerCouldNotFindFileAtPath(normalizedPath);
+ Log.ViewCompilerCouldNotFindFileAtPath(_logger, normalizedPath);
// If the file doesn't exist, we can't do compilation right now - we still want to cache
// the fact that we tried. This will allow us to re-trigger compilation if the view file
@@ -285,7 +285,7 @@ private ViewCompilerWorkItem CreateRuntimeCompilationWorkItem(string normalizedP
};
}
- _logger.ViewCompilerFoundFileToCompile(normalizedPath);
+ Log.ViewCompilerFoundFileToCompile(_logger, normalizedPath);
GetChangeTokensFromImports(expirationTokens, projectItem);
@@ -353,7 +353,7 @@ protected virtual CompiledViewDescriptor CompileAndEmit(string relativePath)
internal Assembly CompileAndEmit(RazorCodeDocument codeDocument, string generatedCode)
{
- _logger.GeneratedCodeToAssemblyCompilationStart(codeDocument.Source.FilePath);
+ Log.GeneratedCodeToAssemblyCompilationStart(_logger, codeDocument.Source.FilePath);
var startTimestamp = _logger.IsEnabled(LogLevel.Debug) ? Stopwatch.GetTimestamp() : 0;
@@ -384,7 +384,7 @@ internal Assembly CompileAndEmit(RazorCodeDocument codeDocument, string generate
pdbStream?.Seek(0, SeekOrigin.Begin);
var assembly = Assembly.Load(assemblyStream.ToArray(), pdbStream?.ToArray());
- _logger.GeneratedCodeToAssemblyCompilationEnd(codeDocument.Source.FilePath, startTimestamp);
+ Log.GeneratedCodeToAssemblyCompilationEnd(_logger, codeDocument.Source.FilePath, startTimestamp);
return assembly;
}
@@ -426,4 +426,47 @@ private class ViewCompilerWorkItem
public CompiledViewDescriptor Descriptor { get; set; } = default!;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Debug, "Compilation of the generated code for the Razor file at '{FilePath}' started.")]
+ public static partial void GeneratedCodeToAssemblyCompilationStart(ILogger logger, string filePath);
+
+ [LoggerMessage(2, LogLevel.Debug, "Compilation of the generated code for the Razor file at '{FilePath}' completed in {ElapsedMilliseconds}ms.")]
+ private static partial void GeneratedCodeToAssemblyCompilationEnd(ILogger logger, string filePath, double elapsedMilliseconds);
+
+ public static void GeneratedCodeToAssemblyCompilationEnd(ILogger logger, string filePath, long startTimestamp)
+ {
+ // Don't log if logging wasn't enabled at start of request as time will be wildly wrong.
+ if (startTimestamp != 0)
+ {
+ var currentTimestamp = Stopwatch.GetTimestamp();
+ var elapsed = new TimeSpan((long)(TimestampToTicks * (currentTimestamp - startTimestamp)));
+ GeneratedCodeToAssemblyCompilationEnd(logger, filePath, elapsed.TotalMilliseconds);
+ }
+ }
+
+ private static readonly double TimestampToTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
+
+ [LoggerMessage(3, LogLevel.Debug, "Initializing Razor view compiler with compiled view: '{ViewName}'.")]
+ public static partial void ViewCompilerLocatedCompiledView(ILogger logger, string viewName);
+
+ [LoggerMessage(4, LogLevel.Debug, "Initializing Razor view compiler with no compiled views.")]
+ public static partial void ViewCompilerNoCompiledViewsFound(ILogger logger);
+
+ [LoggerMessage(5, LogLevel.Trace, "Located compiled view for view at path '{Path}'.")]
+ public static partial void ViewCompilerLocatedCompiledViewForPath(ILogger logger, string path);
+
+ [LoggerMessage(6, LogLevel.Trace, "Invalidating compiled view for view at path '{Path}'.")]
+ public static partial void ViewCompilerRecompilingCompiledView(ILogger logger, string path);
+
+ [LoggerMessage(7, LogLevel.Trace, "Could not find a file for view at path '{Path}'.")]
+ public static partial void ViewCompilerCouldNotFindFileAtPath(ILogger logger, string path);
+
+ [LoggerMessage(8, LogLevel.Trace, "Found file at path '{Path}'.")]
+ public static partial void ViewCompilerFoundFileToCompile(ILogger logger, string path);
+
+ [LoggerMessage(9, LogLevel.Trace, "Invalidating compiled view at path '{Path}' with a file since the checksum did not match.")]
+ public static partial void ViewCompilerInvalidatingCompiledFile(ILogger logger, string path);
+ }
}
diff --git a/src/Mvc/Mvc.Razor/src/Compilation/DefaultViewCompiler.cs b/src/Mvc/Mvc.Razor/src/Compilation/DefaultViewCompiler.cs
index a34fa834f1dd..97cb48b2636b 100644
--- a/src/Mvc/Mvc.Razor/src/Compilation/DefaultViewCompiler.cs
+++ b/src/Mvc/Mvc.Razor/src/Compilation/DefaultViewCompiler.cs
@@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Compilation;
/// Caches the result of runtime compilation of Razor files for the duration of the application lifetime.
///
// This name is hardcoded in RazorRuntimeCompilationMvcCoreBuilderExtensions. Make sure it's updated if this is ever renamed.
-internal class DefaultViewCompiler : IViewCompiler
+internal partial class DefaultViewCompiler : IViewCompiler
{
private readonly ApplicationPartManager _applicationPartManager;
private readonly ConcurrentDictionary _normalizedPathCache;
@@ -53,7 +53,7 @@ private void EnsureCompiledViews(ILogger logger)
foreach (var compiledView in viewsFeature.ViewDescriptors)
{
- logger.ViewCompilerLocatedCompiledView(compiledView.RelativePath);
+ Log.ViewCompilerLocatedCompiledView(logger, compiledView.RelativePath);
if (!compiledViews.ContainsKey(compiledView.RelativePath))
{
@@ -65,7 +65,7 @@ private void EnsureCompiledViews(ILogger logger)
if (compiledViews.Count == 0)
{
- logger.ViewCompilerNoCompiledViewsFound();
+ Log.ViewCompilerNoCompiledViewsFound(logger);
}
// Safe races should be ok. We would end up logging multiple times
@@ -108,7 +108,7 @@ public Task CompileAsync(string relativePath)
}
// Entry does not exist. Attempt to create one.
- _logger.ViewCompilerCouldNotFindFileAtPath(relativePath);
+ Log.ViewCompilerCouldNotFindFileAtPath(_logger, relativePath);
return Task.FromResult(new CompiledViewDescriptor
{
RelativePath = normalizedPath,
@@ -132,4 +132,16 @@ private string GetNormalizedPath(string relativePath)
return normalizedPath;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(3, LogLevel.Debug, "Initializing Razor view compiler with compiled view: '{ViewName}'.", EventName = "ViewCompilerLocatedCompiledView")]
+ public static partial void ViewCompilerLocatedCompiledView(ILogger logger, string viewName);
+
+ [LoggerMessage(4, LogLevel.Debug, "Initializing Razor view compiler with no compiled views.", EventName = "ViewCompilerNoCompiledViewsFound")]
+ public static partial void ViewCompilerNoCompiledViewsFound(ILogger logger);
+
+ [LoggerMessage(7, LogLevel.Trace, "Could not find a file for view at path '{Path}'.", EventName = "ViewCompilerCouldNotFindFileAtPath")]
+ public static partial void ViewCompilerCouldNotFindFileAtPath(ILogger logger, string path);
+ }
}
diff --git a/src/Mvc/Mvc.Razor/src/RazorViewEngine.cs b/src/Mvc/Mvc.Razor/src/RazorViewEngine.cs
index bf2fd5b3ce24..70af1b03a14a 100644
--- a/src/Mvc/Mvc.Razor/src/RazorViewEngine.cs
+++ b/src/Mvc/Mvc.Razor/src/RazorViewEngine.cs
@@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor;
/// by default. For the controllers in an area, views should exist in
/// .
///
-public class RazorViewEngine : IRazorViewEngine
+public partial class RazorViewEngine : IRazorViewEngine
{
///
/// The view extension
@@ -280,12 +280,12 @@ private ViewLocationCacheResult LocatePageFromViewLocations(
if (!ViewLookupCache.TryGetValue(cacheKey, out ViewLocationCacheResult cacheResult))
{
- _logger.ViewLookupCacheMiss(cacheKey.ViewName, cacheKey.ControllerName);
+ Log.ViewLookupCacheMiss(_logger, cacheKey.ViewName, cacheKey.ControllerName);
cacheResult = OnCacheMiss(expanderContext, cacheKey);
}
else
{
- _logger.ViewLookupCacheHit(cacheKey.ViewName, cacheKey.ControllerName);
+ Log.ViewLookupCacheHit(_logger, cacheKey.ViewName, cacheKey.ControllerName);
}
return cacheResult;
@@ -508,4 +508,13 @@ private static bool IsRelativePath(string name)
// Though ./ViewName looks like a relative path, framework searches for that view using view locations.
return name.EndsWith(ViewExtension, StringComparison.OrdinalIgnoreCase);
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Debug, "View lookup cache miss for view '{ViewName}' in controller '{ControllerName}'.", EventName = "ViewLookupCacheMiss")]
+ public static partial void ViewLookupCacheMiss(ILogger logger, string viewName, string? controllerName);
+
+ [LoggerMessage(2, LogLevel.Debug, "View lookup cache hit for view '{ViewName}' in controller '{ControllerName}'.", EventName = "ViewLookupCacheHit")]
+ public static partial void ViewLookupCacheHit(ILogger logger, string viewName, string? controllerName);
+ }
}
diff --git a/src/Mvc/Mvc.Razor/src/TagHelpers/TagHelperComponentTagHelper.cs b/src/Mvc/Mvc.Razor/src/TagHelpers/TagHelperComponentTagHelper.cs
index fd100e825ba1..58567bdad48c 100644
--- a/src/Mvc/Mvc.Razor/src/TagHelpers/TagHelperComponentTagHelper.cs
+++ b/src/Mvc/Mvc.Razor/src/TagHelpers/TagHelperComponentTagHelper.cs
@@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
/// Initializes and processes the s added to the
/// in the specified order.
///
-public abstract class TagHelperComponentTagHelper : TagHelper
+public abstract partial class TagHelperComponentTagHelper : TagHelper
{
private readonly ILogger _logger;
private readonly IEnumerable _components;
@@ -75,7 +75,7 @@ public override void Init(TagHelperContext context)
component.Init(context);
if (_logger.IsEnabled(LogLevel.Debug))
{
- _logger.TagHelperComponentInitialized(component.GetType().FullName!);
+ Log.TagHelperComponentInitialized(_logger, component.GetType().FullName!);
}
}
}
@@ -88,8 +88,17 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu
await component.ProcessAsync(context, output);
if (_logger.IsEnabled(LogLevel.Debug))
{
- _logger.TagHelperComponentProcessed(component.GetType().FullName!);
+ Log.TagHelperComponentProcessed(_logger, component.GetType().FullName!);
}
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(2, LogLevel.Debug, "Tag helper component '{ComponentName}' initialized.", EventName = "TagHelperComponentInitialized")]
+ public static partial void TagHelperComponentInitialized(ILogger logger, string componentName);
+
+ [LoggerMessage(3, LogLevel.Debug, "Tag helper component '{ComponentName}' processed.", EventName = "TagHelperComponentProcessed")]
+ public static partial void TagHelperComponentProcessed(ILogger logger, string componentName);
+ }
}
diff --git a/src/Mvc/Mvc.TagHelpers/src/Cache/DistributedCacheTagHelperService.cs b/src/Mvc/Mvc.TagHelpers/src/Cache/DistributedCacheTagHelperService.cs
index cd6bd158e6ba..d296cdb2c8b8 100644
--- a/src/Mvc/Mvc.TagHelpers/src/Cache/DistributedCacheTagHelperService.cs
+++ b/src/Mvc/Mvc.TagHelpers/src/Cache/DistributedCacheTagHelperService.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Concurrent;
@@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache;
///
///
///
-public class DistributedCacheTagHelperService : IDistributedCacheTagHelperService
+public partial class DistributedCacheTagHelperService : IDistributedCacheTagHelperService
{
private readonly IDistributedCacheTagHelperStorage _storage;
private readonly IDistributedCacheTagHelperFormatter _formatter;
@@ -139,7 +139,7 @@ public async Task ProcessContentAsync(TagHelperOutput output, Cach
}
catch (Exception e)
{
- _logger.DistributedFormatterDeserializationException(storageKey, e);
+ Log.DistributedFormatterDeserializationException(_logger, storageKey, e);
}
finally
{
@@ -213,4 +213,10 @@ private static byte[] Decode(byte[] value, byte[] expectedKey)
return decoded;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Error, "Couldn't deserialize cached value for key {Key}.", EventName = "DistributedFormatterDeserializationException")]
+ public static partial void DistributedFormatterDeserializationException(ILogger logger, string key, Exception exception);
+ }
}
diff --git a/src/Mvc/Mvc.TagHelpers/src/MvcTagHelpersLoggerExtensions.cs b/src/Mvc/Mvc.TagHelpers/src/MvcTagHelpersLoggerExtensions.cs
deleted file mode 100644
index e88cd6bf74d0..000000000000
--- a/src/Mvc/Mvc.TagHelpers/src/MvcTagHelpersLoggerExtensions.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Microsoft.Extensions.Logging;
-
-namespace Microsoft.AspNetCore.Mvc.TagHelpers;
-
-internal static class MvcTagHelperLoggerExtensions
-{
- private static readonly Action _distributedFormatterDeserializedFailed = LoggerMessage.Define(
- LogLevel.Error,
- new EventId(1, "DistributedFormatterDeserializationException"),
- "Couldn't deserialize cached value for key {Key}.");
-
- public static void DistributedFormatterDeserializationException(this ILogger logger, string key, Exception exception)
- {
- _distributedFormatterDeserializedFailed(logger, key, exception);
- }
-}
diff --git a/src/Mvc/Mvc.ViewFeatures/src/CookieTempDataProvider.cs b/src/Mvc/Mvc.ViewFeatures/src/CookieTempDataProvider.cs
index 212cc89679d9..f924dd58e75c 100644
--- a/src/Mvc/Mvc.ViewFeatures/src/CookieTempDataProvider.cs
+++ b/src/Mvc/Mvc.ViewFeatures/src/CookieTempDataProvider.cs
@@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures;
///
/// Provides data from cookie to the current object.
///
-public class CookieTempDataProvider : ITempDataProvider
+public partial class CookieTempDataProvider : ITempDataProvider
{
///
/// The name of the cookie.
@@ -76,14 +76,13 @@ public IDictionary LoadTempData(HttpContext context)
var protectedData = WebEncoders.Base64UrlDecode(encodedValue);
var unprotectedData = _dataProtector.Unprotect(protectedData);
var tempData = _tempDataSerializer.Deserialize(unprotectedData);
-
- _logger.TempDataCookieLoadSuccess(_options.Cookie.Name);
+ Log.TempDataCookieLoadSuccess(_logger, _options.Cookie.Name);
return tempData;
}
}
catch (Exception ex)
{
- _logger.TempDataCookieLoadFailure(_options.Cookie.Name, ex);
+ Log.TempDataCookieLoadFailure(_logger, _options.Cookie.Name, ex);
// If we've failed, we want to try and clear the cookie so that this won't keep happening
// over and over.
@@ -94,7 +93,7 @@ public IDictionary LoadTempData(HttpContext context)
}
}
- _logger.TempDataCookieNotFound(_options.Cookie.Name);
+ Log.TempDataCookieNotFound(_logger, _options.Cookie.Name);
return new Dictionary(StringComparer.OrdinalIgnoreCase);
}
@@ -142,4 +141,16 @@ private void SetCookiePath(HttpContext httpContext, CookieOptions cookieOptions)
}
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Debug, "The temp data cookie {CookieName} was not found.", EventName = "TempDataCookieNotFound")]
+ public static partial void TempDataCookieNotFound(ILogger logger, string cookieName);
+
+ [LoggerMessage(2, LogLevel.Debug, "The temp data cookie {CookieName} was used to successfully load temp data.", EventName = "TempDataCookieLoadSuccess")]
+ public static partial void TempDataCookieLoadSuccess(ILogger logger, string cookieName);
+
+ [LoggerMessage(3, LogLevel.Warning, "The temp data cookie {CookieName} could not be loaded.", EventName = "TempDataCookieLoadFailure")]
+ public static partial void TempDataCookieLoadFailure(ILogger logger, string cookieName, Exception exception);
+ }
}
diff --git a/src/Mvc/Mvc.ViewFeatures/src/Filters/ValidateAntiforgeryTokenAuthorizationFilter.cs b/src/Mvc/Mvc.ViewFeatures/src/Filters/ValidateAntiforgeryTokenAuthorizationFilter.cs
index f5816b221dda..15095473dcfb 100644
--- a/src/Mvc/Mvc.ViewFeatures/src/Filters/ValidateAntiforgeryTokenAuthorizationFilter.cs
+++ b/src/Mvc/Mvc.ViewFeatures/src/Filters/ValidateAntiforgeryTokenAuthorizationFilter.cs
@@ -7,7 +7,7 @@
namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters;
-internal class ValidateAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizationFilter, IAntiforgeryPolicy
+internal partial class ValidateAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizationFilter, IAntiforgeryPolicy
{
private readonly IAntiforgery _antiforgery;
private readonly ILogger _logger;
@@ -32,7 +32,7 @@ public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
if (!context.IsEffectivePolicy(this))
{
- _logger.NotMostEffectiveFilter(typeof(IAntiforgeryPolicy));
+ Log.NotMostEffectiveFilter(_logger, typeof(IAntiforgeryPolicy));
return;
}
@@ -44,7 +44,7 @@ public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
}
catch (AntiforgeryValidationException exception)
{
- _logger.AntiforgeryTokenInvalid(exception.Message, exception);
+ Log.AntiforgeryTokenInvalid(_logger, exception.Message, exception);
context.Result = new AntiforgeryValidationFailedResult();
}
}
@@ -59,4 +59,13 @@ protected virtual bool ShouldValidate(AuthorizationFilterContext context)
return true;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Antiforgery token validation failed. {Message}", EventName = "AntiforgeryTokenInvalid")]
+ public static partial void AntiforgeryTokenInvalid(ILogger logger, string message, Exception exception);
+
+ [LoggerMessage(2, LogLevel.Trace, "Skipping the execution of current filter as its not the most effective filter implementing the policy {FilterPolicy}.", EventName = "NotMostEffectiveFilter")]
+ public static partial void NotMostEffectiveFilter(ILogger logger, Type filterPolicy);
+ }
}
diff --git a/src/Mvc/Mvc.ViewFeatures/src/MvcViewFeaturesLoggerExtensions.cs b/src/Mvc/Mvc.ViewFeatures/src/MvcViewFeaturesLoggerExtensions.cs
deleted file mode 100644
index 82fe74dae614..000000000000
--- a/src/Mvc/Mvc.ViewFeatures/src/MvcViewFeaturesLoggerExtensions.cs
+++ /dev/null
@@ -1,312 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections;
-using System.Globalization;
-using Microsoft.AspNetCore.Mvc.ViewComponents;
-using Microsoft.AspNetCore.Mvc.ViewEngines;
-using Microsoft.Extensions.Logging;
-
-namespace Microsoft.AspNetCore.Mvc.ViewFeatures;
-
-internal static class MvcViewFeaturesLoggerExtensions
-{
- private static readonly Action _viewComponentExecuting;
- private static readonly Action _viewComponentExecuted;
-
- private static readonly Action _partialViewFound;
- private static readonly Action, Exception> _partialViewNotFound;
- private static readonly Action _partialViewResultExecuting;
- private static readonly Action _partialViewResultExecuted;
-
- private static readonly Action _antiforgeryTokenInvalid;
-
- private static readonly Action _viewComponentResultExecuting;
-
- private static readonly Action _viewResultExecuting;
- private static readonly Action _viewResultExecuted;
- private static readonly Action _viewFound;
- private static readonly Action, Exception> _viewNotFound;
-
- private static readonly Action _tempDataCookieNotFound;
- private static readonly Action _tempDataCookieLoadSuccess;
- private static readonly Action _tempDataCookieLoadFailure;
-
- private static readonly Action _notMostEffectiveFilter;
-
- private static readonly LogDefineOptions SkipEnabledCheckLogOptions = new() { SkipEnabledCheck = true };
-
- static MvcViewFeaturesLoggerExtensions()
- {
- _viewComponentExecuting = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(1, "ViewComponentExecuting"),
- "Executing view component {ViewComponentName} with arguments ({Arguments}).",
- SkipEnabledCheckLogOptions);
-
- _viewComponentExecuted = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(2, "ViewComponentExecuted"),
- "Executed view component {ViewComponentName} in {ElapsedMilliseconds}ms and returned " +
- "{ViewComponentResult}",
- SkipEnabledCheckLogOptions);
-
- _partialViewResultExecuting = LoggerMessage.Define(
- LogLevel.Information,
- new EventId(1, "PartialViewResultExecuting"),
- "Executing PartialViewResult, running view {PartialViewName}.");
-
- _partialViewFound = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(2, "PartialViewFound"),
- "The partial view path '{PartialViewFilePath}' was found in {ElapsedMilliseconds}ms.");
-
- _partialViewNotFound = LoggerMessage.Define>(
- LogLevel.Error,
- new EventId(3, "PartialViewNotFound"),
- "The partial view '{PartialViewName}' was not found. Searched locations: {SearchedViewLocations}");
-
- _partialViewResultExecuted = LoggerMessage.Define(
- LogLevel.Information,
- new EventId(4, "PartialViewResultExecuted"),
- "Executed PartialViewResult - view {PartialViewName} executed in {ElapsedMilliseconds}ms.");
-
- _antiforgeryTokenInvalid = LoggerMessage.Define(
- LogLevel.Information,
- new EventId(1, "AntiforgeryTokenInvalid"),
- "Antiforgery token validation failed. {Message}");
-
- _viewComponentResultExecuting = LoggerMessage.Define(
- LogLevel.Information,
- new EventId(1, "ViewComponentResultExecuting"),
- "Executing ViewComponentResult, running {ViewComponentName}.",
- SkipEnabledCheckLogOptions);
-
- _viewResultExecuting = LoggerMessage.Define(
- LogLevel.Information,
- new EventId(1, "ViewResultExecuting"),
- "Executing ViewResult, running view {ViewName}.");
-
- _viewFound = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(2, "ViewFound"),
- "The view path '{ViewFilePath}' was found in {ElapsedMilliseconds}ms.");
-
- _viewNotFound = LoggerMessage.Define>(
- LogLevel.Error,
- new EventId(3, "ViewNotFound"),
- "The view '{ViewName}' was not found. Searched locations: {SearchedViewLocations}");
-
- _viewResultExecuted = LoggerMessage.Define(
- LogLevel.Information,
- new EventId(4, "ViewResultExecuted"),
- "Executed ViewResult - view {ViewName} executed in {ElapsedMilliseconds}ms.");
-
- _tempDataCookieNotFound = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(1, "TempDataCookieNotFound"),
- "The temp data cookie {CookieName} was not found.");
-
- _tempDataCookieLoadSuccess = LoggerMessage.Define(
- LogLevel.Debug,
- new EventId(2, "TempDataCookieLoadSuccess"),
- "The temp data cookie {CookieName} was used to successfully load temp data.");
-
- _tempDataCookieLoadFailure = LoggerMessage.Define(
- LogLevel.Warning,
- new EventId(3, "TempDataCookieLoadFailure"),
- "The temp data cookie {CookieName} could not be loaded.");
-
- _notMostEffectiveFilter = LoggerMessage.Define(
- LogLevel.Trace,
- new EventId(1, "NotMostEffectiveFilter"),
- "Skipping the execution of current filter as its not the most effective filter implementing the policy {FilterPolicy}.");
- }
-
-#nullable enable
- public static IDisposable? ViewComponentScope(this ILogger logger, ViewComponentContext context)
- {
- return logger.BeginScope(new ViewComponentLogScope(context.ViewComponentDescriptor));
- }
-#nullable restore
-
- public static void ViewComponentExecuting(
- this ILogger logger,
- ViewComponentContext context,
- object[] arguments)
- {
- if (logger.IsEnabled(LogLevel.Debug))
- {
- var formattedArguments = GetFormattedArguments(arguments);
- _viewComponentExecuting(logger, context.ViewComponentDescriptor.DisplayName, formattedArguments, null);
- }
- }
-
- private static string[] GetFormattedArguments(object[] arguments)
- {
- if (arguments == null || arguments.Length == 0)
- {
- return Array.Empty();
- }
-
- var formattedArguments = new string[arguments.Length];
- for (var i = 0; i < formattedArguments.Length; i++)
- {
- formattedArguments[i] = Convert.ToString(arguments[i], CultureInfo.InvariantCulture);
- }
-
- return formattedArguments;
- }
-
- public static void ViewComponentExecuted(
- this ILogger logger,
- ViewComponentContext context,
- TimeSpan timespan,
- object result)
- {
- // Don't log if logging wasn't enabled at start of request as time will be wildly wrong.
- if (logger.IsEnabled(LogLevel.Debug))
- {
- _viewComponentExecuted(
- logger,
- context.ViewComponentDescriptor.DisplayName,
- timespan.TotalMilliseconds,
- Convert.ToString(result, CultureInfo.InvariantCulture),
- null);
- }
- }
-
- public static void PartialViewFound(
- this ILogger logger,
- IView view,
- TimeSpan timespan)
- {
- _partialViewFound(logger, view.Path, timespan.TotalMilliseconds, null);
- }
-
- public static void PartialViewNotFound(
- this ILogger logger,
- string partialViewName,
- IEnumerable searchedLocations)
- {
- _partialViewNotFound(logger, partialViewName, searchedLocations, null);
- }
-
- public static void PartialViewResultExecuting(this ILogger logger, string partialViewName)
- {
- _partialViewResultExecuting(logger, partialViewName, null);
- }
-
- public static void PartialViewResultExecuted(this ILogger logger, string partialViewName, TimeSpan timespan)
- {
- _partialViewResultExecuted(logger, partialViewName, timespan.TotalMilliseconds, null);
- }
-
- public static void AntiforgeryTokenInvalid(this ILogger logger, string message, Exception exception)
- {
- _antiforgeryTokenInvalid(logger, message, exception);
- }
-
- public static void ViewComponentResultExecuting(this ILogger logger, string viewComponentName)
- {
- if (logger.IsEnabled(LogLevel.Information))
- {
- _viewComponentResultExecuting(logger, viewComponentName, null);
- }
- }
-
- public static void ViewComponentResultExecuting(this ILogger logger, Type viewComponentType)
- {
- if (logger.IsEnabled(LogLevel.Information))
- {
- _viewComponentResultExecuting(logger, viewComponentType.Name, null);
- }
- }
-
- public static void ViewResultExecuting(this ILogger logger, string viewName)
- {
- _viewResultExecuting(logger, viewName, null);
- }
-
- public static void ViewResultExecuted(this ILogger logger, string viewName, TimeSpan timespan)
- {
- _viewResultExecuted(logger, viewName, timespan.TotalMilliseconds, null);
- }
-
- public static void ViewFound(this ILogger logger, IView view, TimeSpan timespan)
- {
- _viewFound(logger, view.Path, timespan.TotalMilliseconds, null);
- }
-
- public static void ViewNotFound(this ILogger logger, string viewName,
- IEnumerable searchedLocations)
- {
- _viewNotFound(logger, viewName, searchedLocations, null);
- }
-
- public static void TempDataCookieNotFound(this ILogger logger, string cookieName)
- {
- _tempDataCookieNotFound(logger, cookieName, null);
- }
-
- public static void TempDataCookieLoadSuccess(this ILogger logger, string cookieName)
- {
- _tempDataCookieLoadSuccess(logger, cookieName, null);
- }
-
- public static void TempDataCookieLoadFailure(this ILogger logger, string cookieName, Exception exception)
- {
- _tempDataCookieLoadFailure(logger, cookieName, exception);
- }
-
- public static void NotMostEffectiveFilter(this ILogger logger, Type policyType)
- {
- _notMostEffectiveFilter(logger, policyType, null);
- }
-
- private class ViewComponentLogScope : IReadOnlyList>
- {
- private readonly ViewComponentDescriptor _descriptor;
-
- public ViewComponentLogScope(ViewComponentDescriptor descriptor)
- {
- _descriptor = descriptor;
- }
-
- public KeyValuePair this[int index]
- {
- get
- {
- if (index == 0)
- {
- return new KeyValuePair("ViewComponentName", _descriptor.DisplayName);
- }
- else if (index == 1)
- {
- return new KeyValuePair("ViewComponentId", _descriptor.Id);
- }
- throw new IndexOutOfRangeException(nameof(index));
- }
- }
-
- public int Count => 2;
-
- public IEnumerator> GetEnumerator()
- {
- for (var i = 0; i < Count; ++i)
- {
- yield return this[i];
- }
- }
-
- public override string ToString()
- {
- return _descriptor.DisplayName;
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
-}
diff --git a/src/Mvc/Mvc.ViewFeatures/src/PartialViewResultExecutor.cs b/src/Mvc/Mvc.ViewFeatures/src/PartialViewResultExecutor.cs
index 3904f4cc0c5e..4a05f8281694 100644
--- a/src/Mvc/Mvc.ViewFeatures/src/PartialViewResultExecutor.cs
+++ b/src/Mvc/Mvc.ViewFeatures/src/PartialViewResultExecutor.cs
@@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures;
///
/// Finds and executes an for a .
///
-public class PartialViewResultExecutor : ViewExecutor, IActionResultExecutor
+public partial class PartialViewResultExecutor : ViewExecutor, IActionResultExecutor
{
private const string ActionNameKey = "action";
@@ -85,7 +85,7 @@ public virtual ViewEngineResult FindView(ActionContext actionContext, PartialVie
result = viewEngine.FindView(actionContext, viewName, isMainPage: false);
}
- Logger.PartialViewResultExecuting(result.ViewName);
+ Log.PartialViewResultExecuting(Logger, result.ViewName);
if (!result.Success)
{
if (originalResult.SearchedLocations.Any())
@@ -113,8 +113,7 @@ public virtual ViewEngineResult FindView(ActionContext actionContext, PartialVie
viewResult: viewResult,
viewName: viewName,
view: result.View);
-
- Logger.PartialViewFound(result.View, stopwatch.GetElapsedTime());
+ Log.PartialViewFound(Logger, result.View, stopwatch.GetElapsedTime());
}
else
{
@@ -124,8 +123,7 @@ public virtual ViewEngineResult FindView(ActionContext actionContext, PartialVie
viewResult: viewResult,
viewName: viewName,
searchedLocations: result.SearchedLocations);
-
- Logger.PartialViewNotFound(viewName, result.SearchedLocations);
+ Log.PartialViewNotFound(Logger, viewName, result.SearchedLocations);
}
return result;
@@ -188,7 +186,7 @@ public virtual async Task ExecuteAsync(ActionContext context, PartialViewResult
await ExecuteAsync(context, view, result);
}
- Logger.PartialViewResultExecuted(result.ViewName, stopwatch.GetElapsedTime());
+ Log.PartialViewResultExecuted(Logger, result.ViewName, stopwatch.GetElapsedTime());
}
private static string? GetActionName(ActionContext context)
@@ -219,4 +217,29 @@ public virtual async Task ExecuteAsync(ActionContext context, PartialViewResult
return stringRouteValue;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing PartialViewResult, running view {PartialViewName}.", EventName = "PartialViewResultExecuting")]
+ public static partial void PartialViewResultExecuting(ILogger logger, string partialViewName);
+
+ [LoggerMessage(2, LogLevel.Debug, "The partial view path '{PartialViewFilePath}' was found in {ElapsedMilliseconds}ms.", EventName = "PartialViewFound")]
+ private static partial void PartialViewFound(ILogger logger, string partialViewFilePath, double elapsedMilliseconds);
+
+ public static void PartialViewFound(ILogger logger, IView view, TimeSpan timespan)
+ {
+ PartialViewFound(logger, view.Path, timespan.TotalMilliseconds);
+ }
+
+ [LoggerMessage(3, LogLevel.Error, "The partial view '{PartialViewName}' was not found. Searched locations: {SearchedViewLocations}", EventName = "PartialViewNotFound")]
+ public static partial void PartialViewNotFound(ILogger logger, string partialViewName, IEnumerable searchedViewLocations);
+
+ [LoggerMessage(4, LogLevel.Information, "Executed PartialViewResult - view {PartialViewName} executed in {ElapsedMilliseconds}ms.", EventName = "PartialViewResultExecuted")]
+ private static partial void PartialViewResultExecuted(ILogger logger, string? partialViewName, double elapsedMilliseconds);
+
+ public static void PartialViewResultExecuted(ILogger logger, string? partialViewName, TimeSpan timespan)
+ {
+ PartialViewResultExecuted(logger, partialViewName, timespan.TotalMilliseconds);
+ }
+ }
}
diff --git a/src/Mvc/Mvc.ViewFeatures/src/ViewComponentResultExecutor.cs b/src/Mvc/Mvc.ViewFeatures/src/ViewComponentResultExecutor.cs
index 33ed8798f0ae..54195048895b 100644
--- a/src/Mvc/Mvc.ViewFeatures/src/ViewComponentResultExecutor.cs
+++ b/src/Mvc/Mvc.ViewFeatures/src/ViewComponentResultExecutor.cs
@@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures;
///
/// A for .
///
-public class ViewComponentResultExecutor : IActionResultExecutor
+public partial class ViewComponentResultExecutor : IActionResultExecutor
{
private readonly HtmlEncoder _htmlEncoder;
private readonly HtmlHelperOptions _htmlHelperOptions;
@@ -178,13 +178,24 @@ private static Task GetViewComponentResult(IViewComponentHelper vi
}
else if (result.ViewComponentType == null)
{
- logger.ViewComponentResultExecuting(result.ViewComponentName);
+ Log.ViewComponentResultExecuting(logger, result.ViewComponentName);
return viewComponentHelper.InvokeAsync(result.ViewComponentName!, result.Arguments);
}
else
{
- logger.ViewComponentResultExecuting(result.ViewComponentType);
+ Log.ViewComponentResultExecuting(_logger, result.ViewComponentType);
return viewComponentHelper.InvokeAsync(result.ViewComponentType, result.Arguments);
}
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing ViewComponentResult, running {ViewComponentName}.", EventName = "ViewComponentResultExecuting")]
+ public static partial void ViewComponentResultExecuting(ILogger logger, string? viewComponentName);
+
+ public static void ViewComponentResultExecuting(ILogger logger, Type viewComponentType)
+ {
+ ViewComponentResultExecuting(logger, viewComponentType.Name);
+ }
+ }
}
diff --git a/src/Mvc/Mvc.ViewFeatures/src/ViewComponents/DefaultViewComponentInvoker.cs b/src/Mvc/Mvc.ViewFeatures/src/ViewComponents/DefaultViewComponentInvoker.cs
index cd0b2df7e4ef..e48ed6a820d0 100644
--- a/src/Mvc/Mvc.ViewFeatures/src/ViewComponents/DefaultViewComponentInvoker.cs
+++ b/src/Mvc/Mvc.ViewFeatures/src/ViewComponents/DefaultViewComponentInvoker.cs
@@ -3,7 +3,9 @@
#nullable enable
+using System.Collections;
using System.Diagnostics;
+using System.Globalization;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.Internal;
@@ -14,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents;
///
/// Default implementation for .
///
-internal class DefaultViewComponentInvoker : IViewComponentInvoker
+internal partial class DefaultViewComponentInvoker : IViewComponentInvoker
{
private readonly IViewComponentFactory _viewComponentFactory;
private readonly ViewComponentInvokerCache _viewComponentInvokerCache;
@@ -106,12 +108,12 @@ public async Task InvokeAsync(ViewComponentContext context)
private async Task InvokeAsyncCore(ObjectMethodExecutor executor, object component, ViewComponentContext context)
{
- using (_logger.ViewComponentScope(context))
+ using (Log.ViewComponentScope(_logger, context))
{
var arguments = PrepareArguments(context.Arguments, executor);
_diagnosticListener.BeforeViewComponent(context, component);
- _logger.ViewComponentExecuting(context, arguments);
+ Log.ViewComponentExecuting(_logger, context, arguments);
var stopwatch = ValueStopwatch.StartNew();
@@ -154,7 +156,7 @@ private async Task InvokeAsyncCore(ObjectMethodExecutor ex
}
var viewComponentResult = CoerceToViewComponentResult(resultAsObject);
- _logger.ViewComponentExecuted(context, stopwatch.GetElapsedTime(), viewComponentResult);
+ Log.ViewComponentExecuted(_logger, context, stopwatch.GetElapsedTime(), viewComponentResult);
_diagnosticListener.AfterViewComponent(context, viewComponentResult, component);
return viewComponentResult;
@@ -163,12 +165,12 @@ private async Task InvokeAsyncCore(ObjectMethodExecutor ex
private IViewComponentResult InvokeSyncCore(ObjectMethodExecutor executor, object component, ViewComponentContext context)
{
- using (_logger.ViewComponentScope(context))
+ using (Log.ViewComponentScope(_logger, context))
{
var arguments = PrepareArguments(context.Arguments, executor);
_diagnosticListener.BeforeViewComponent(context, component);
- _logger.ViewComponentExecuting(context, arguments);
+ Log.ViewComponentExecuting(_logger, context, arguments);
var stopwatch = ValueStopwatch.StartNew();
object? result;
@@ -176,7 +178,7 @@ private IViewComponentResult InvokeSyncCore(ObjectMethodExecutor executor, objec
result = executor.Execute(component, arguments);
var viewComponentResult = CoerceToViewComponentResult(result);
- _logger.ViewComponentExecuted(context, stopwatch.GetElapsedTime(), viewComponentResult);
+ Log.ViewComponentExecuted(_logger, context, stopwatch.GetElapsedTime(), viewComponentResult);
_diagnosticListener.AfterViewComponent(context, viewComponentResult, component);
return viewComponentResult;
@@ -237,4 +239,110 @@ private static IViewComponentResult CoerceToViewComponentResult(object? value)
return arguments;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Debug, "Executing view component {ViewComponentName} with arguments ({Arguments}).", EventName = "ViewComponentExecuting", SkipEnabledCheck = true)]
+ private static partial void ViewComponentExecuting(ILogger logger, string viewComponentName, string[] arguments);
+
+ [LoggerMessage(2, LogLevel.Debug, "Executed view component {ViewComponentName} in {ElapsedMilliseconds}ms and returned {ViewComponentResult}", EventName = "ViewComponentExecuted", SkipEnabledCheck = true)]
+ private static partial void ViewComponentExecuted(ILogger logger, string viewComponentName, double elapsedMilliseconds, string? viewComponentResult);
+
+ public static IDisposable? ViewComponentScope(ILogger logger, ViewComponentContext context)
+ {
+ return logger.BeginScope(new ViewComponentLogScope(context.ViewComponentDescriptor));
+ }
+
+#nullable restore
+ public static void ViewComponentExecuting(
+ ILogger logger,
+ ViewComponentContext context,
+ object[] arguments)
+ {
+ if (logger.IsEnabled(LogLevel.Debug))
+ {
+ var formattedArguments = GetFormattedArguments(arguments);
+ ViewComponentExecuting(logger, context.ViewComponentDescriptor.DisplayName, formattedArguments);
+ }
+ }
+
+ public static void ViewComponentExecuted(
+ ILogger logger,
+ ViewComponentContext context,
+ TimeSpan timespan,
+ object result)
+ {
+ // Don't log if logging wasn't enabled at start of request as time will be wildly wrong.
+ if (logger.IsEnabled(LogLevel.Debug))
+ {
+ ViewComponentExecuted(
+ logger,
+ context.ViewComponentDescriptor.DisplayName,
+ timespan.TotalMilliseconds,
+ Convert.ToString(result, CultureInfo.InvariantCulture));
+ }
+ }
+
+ private static string[] GetFormattedArguments(object[] arguments)
+ {
+ if (arguments == null || arguments.Length == 0)
+ {
+ return Array.Empty();
+ }
+
+ var formattedArguments = new string[arguments.Length];
+ for (var i = 0; i < formattedArguments.Length; i++)
+ {
+ formattedArguments[i] = Convert.ToString(arguments[i], CultureInfo.InvariantCulture);
+ }
+
+ return formattedArguments;
+ }
+
+ private sealed class ViewComponentLogScope : IReadOnlyList>
+ {
+ private readonly ViewComponentDescriptor _descriptor;
+
+ public ViewComponentLogScope(ViewComponentDescriptor descriptor)
+ {
+ _descriptor = descriptor;
+ }
+
+ public KeyValuePair this[int index]
+ {
+ get
+ {
+ if (index == 0)
+ {
+ return new KeyValuePair("ViewComponentName", _descriptor.DisplayName);
+ }
+ else if (index == 1)
+ {
+ return new KeyValuePair("ViewComponentId", _descriptor.Id);
+ }
+ throw new IndexOutOfRangeException(nameof(index));
+ }
+ }
+
+ public int Count => 2;
+
+ public IEnumerator> GetEnumerator()
+ {
+ for (var i = 0; i < Count; ++i)
+ {
+ yield return this[i];
+ }
+ }
+
+ public override string ToString()
+ {
+ return _descriptor.DisplayName;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+ }
}
diff --git a/src/Mvc/Mvc.ViewFeatures/src/ViewResultExecutor.cs b/src/Mvc/Mvc.ViewFeatures/src/ViewResultExecutor.cs
index 0db47f1b1e6a..bde2700da584 100644
--- a/src/Mvc/Mvc.ViewFeatures/src/ViewResultExecutor.cs
+++ b/src/Mvc/Mvc.ViewFeatures/src/ViewResultExecutor.cs
@@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures;
///
/// Finds and executes an for a .
///
-public class ViewResultExecutor : ViewExecutor, IActionResultExecutor
+public partial class ViewResultExecutor : ViewExecutor, IActionResultExecutor
{
private const string ActionNameKey = "action";
@@ -86,7 +86,7 @@ public virtual ViewEngineResult FindView(ActionContext actionContext, ViewResult
result = viewEngine.FindView(actionContext, viewName, isMainPage: true);
}
- Logger.ViewResultExecuting(result.ViewName);
+ Log.ViewResultExecuting(Logger, result.ViewName);
if (!result.Success)
{
if (originalResult.SearchedLocations.Any())
@@ -113,11 +113,11 @@ public virtual ViewEngineResult FindView(ActionContext actionContext, ViewResult
if (result.Success)
{
- Logger.ViewFound(result.View, stopwatch.GetElapsedTime());
+ Log.ViewFound(Logger, result.View, stopwatch.GetElapsedTime());
}
else
{
- Logger.ViewNotFound(viewName, result.SearchedLocations);
+ Log.ViewNotFound(Logger, viewName, result.SearchedLocations);
}
return result;
@@ -175,7 +175,7 @@ await ExecuteAsync(
result.StatusCode);
}
- Logger.ViewResultExecuted(viewEngineResult.ViewName, stopwatch.GetElapsedTime());
+ Log.ViewResultExecuted(Logger, viewEngineResult.ViewName, stopwatch.GetElapsedTime());
}
private static string? GetActionName(ActionContext context)
@@ -206,4 +206,29 @@ await ExecuteAsync(
return stringRouteValue;
}
+
+ private static partial class Log
+ {
+ [LoggerMessage(1, LogLevel.Information, "Executing ViewResult, running view {ViewName}.", EventName = "ViewResultExecuting")]
+ public static partial void ViewResultExecuting(ILogger logger, string viewName);
+
+ [LoggerMessage(2, LogLevel.Debug, "The view path '{ViewFilePath}' was found in {ElapsedMilliseconds}ms.", EventName = "ViewFound")]
+ private static partial void ViewFound(ILogger logger, string viewFilePath, double elapsedMilliseconds);
+
+ public static void ViewFound(ILogger logger, IView view, TimeSpan timespan)
+ {
+ ViewFound(logger, view.Path, timespan.TotalMilliseconds);
+ }
+
+ [LoggerMessage(3, LogLevel.Error, "The view '{ViewName}' was not found. Searched locations: {SearchedViewLocations}", EventName = "ViewNotFound")]
+ public static partial void ViewNotFound(ILogger logger, string viewName, IEnumerable searchedViewLocations);
+
+ [LoggerMessage(4, LogLevel.Information, "Executed ViewResult - view {ViewName} executed in {ElapsedMilliseconds}ms.", EventName = "ViewResultExecuted")]
+ private static partial void ViewResultExecuted(ILogger logger, string viewName, double elapsedMilliseconds);
+
+ public static void ViewResultExecuted(ILogger logger, string viewName, TimeSpan timespan)
+ {
+ ViewResultExecuted(logger, viewName, timespan.TotalMilliseconds);
+ }
+ }
}