diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs index 2050911090..e81af7df95 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs @@ -109,6 +109,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal private static readonly Action _foundNoValueForPropertyInRequest; private static readonly Action _foundNoValueForParameterInRequest; private static readonly Action _foundNoValueInRequest; + private static readonly Action _parameterBinderRequestPredicateShortCircuitOfProperty; + private static readonly Action _parameterBinderRequestPredicateShortCircuitOfParameter; private static readonly Action _noPublicSettableProperties; private static readonly Action _cannotBindToComplexType; private static readonly Action _cannotBindToFilesCollectionDueToUnsupportedContentType; @@ -636,6 +638,16 @@ namespace Microsoft.AspNetCore.Mvc.Internal LogLevel.Debug, 46, "Could not find a value in the request with name '{ModelName}' of type '{ModelType}'."); + + _parameterBinderRequestPredicateShortCircuitOfProperty = LoggerMessage.Define( + LogLevel.Debug, + 47, + "Skipped binding property '{PropertyContainerType}.{PropertyName}' since it's binding information disallowed it for the current request."); + + _parameterBinderRequestPredicateShortCircuitOfParameter = LoggerMessage.Define( + LogLevel.Debug, + 48, + "Skipped binding parameter '{ParameterName}' since it's binding information disallowed it for the current request."); } public static void RegisteredOutputFormatters(this ILogger logger, IEnumerable outputFormatters) @@ -1526,6 +1538,45 @@ namespace Microsoft.AspNetCore.Mvc.Internal null); } + public static void ParameterBinderRequestPredicateShortCircuit( + this ILogger logger, + ModelMetadata modelMetadata, + ParameterDescriptor parameter) + { + switch (modelMetadata.MetadataKind) + { + case ModelMetadataKind.Parameter: + _parameterBinderRequestPredicateShortCircuitOfParameter( + logger, + modelMetadata.ParameterName, + null); + break; + case ModelMetadataKind.Property: + _parameterBinderRequestPredicateShortCircuitOfProperty( + logger, + modelMetadata.ContainerType, + modelMetadata.PropertyName, + null); + break; + case ModelMetadataKind.Type: + if (parameter is ControllerParameterDescriptor controllerParameterDescriptor) + { + _parameterBinderRequestPredicateShortCircuitOfParameter( + logger, + controllerParameterDescriptor.ParameterInfo.Name, + null); + } + else + { + // Likely binding a page handler parameter. Due to various special cases, parameter.Name may + // be empty. No way to determine actual name. This case is less likely than for binding logging + // (above). Should occur only with a legacy IModelMetadataProvider implementation. + _parameterBinderRequestPredicateShortCircuitOfParameter(logger, parameter.Name, null); + } + break; + } + } + private static void LogFilterExecutionPlan( ILogger logger, string filterType, diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs index 90a2458f2a..542ae37902 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs @@ -205,6 +205,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding if (parameter.BindingInfo?.RequestPredicate?.Invoke(actionContext) == false) { + Logger.ParameterBinderRequestPredicateShortCircuit(metadata, parameter); + return ModelBindingResult.Failed(); }