diff --git a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBinderProviderContext.cs b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBinderProviderContext.cs index 2d01d6acb9..eb2136e413 100644 --- a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBinderProviderContext.cs +++ b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBinderProviderContext.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; + namespace Microsoft.AspNetCore.Mvc.ModelBinding { /// @@ -29,5 +31,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// Gets the . /// public abstract IModelMetadataProvider MetadataProvider { get; } + + /// + /// Gets the . + /// + public virtual IServiceProvider Services { get; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs index 03ffe21330..86c4a1968c 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs @@ -20,6 +20,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection @@ -236,10 +237,11 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddSingleton(s => { var options = s.GetRequiredService>().Value; + var loggerFactory = s.GetRequiredService(); var metadataProvider = s.GetRequiredService(); var modelBinderFactory = s.GetRequiredService(); var modelValidatorProvider = new CompositeModelValidatorProvider(options.ModelValidatorProviders); - return new ParameterBinder(metadataProvider, modelBinderFactory, modelValidatorProvider); + return new ParameterBinder(metadataProvider, modelBinderFactory, modelValidatorProvider, loggerFactory); }); // diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs index 4cc0f8f900..d65da95d40 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreLoggerExtensions.cs @@ -11,10 +11,12 @@ using System.Security.Claims; 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; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Formatters.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.Extensions.Internal; using Microsoft.Extensions.Logging; using Microsoft.Net.Http.Headers; @@ -98,7 +100,30 @@ namespace Microsoft.AspNetCore.Mvc.Internal private static readonly Action _inferredParameterSource; private static readonly Action _unableToInferParameterSources; - + private static readonly Action _registeredModelBinderProviders; + private static readonly Action _foundNoValueForPropertyInRequest; + private static readonly Action _foundNoValueInRequest; + private static readonly Action _noPublicSettableProperties; + private static readonly Action _cannotBindToComplexType; + private static readonly Action _cannotBindToFilesCollectionDueToUnsupportedContentType; + private static readonly Action _cannotCreateHeaderModelBinder; + private static readonly Action _noFilesFoundInRequest; + private static readonly Action _noNonIndexBasedFormatFoundForCollection; + private static readonly Action _attemptingToBindCollectionUsingIndices; + private static readonly Action _attemptingToBindCollectionOfKeyValuePair; + private static readonly Action _noKeyValueFormatForDictionaryModelBinder; + private static readonly Action _attemptingToBindPropertyModel; + private static readonly Action _doneAttemptingToBindPropertyModel; + private static readonly Action _attemptingToBindModel; + private static readonly Action _doneAttemptingToBindModel; + private static readonly Action _attemptingToBindParameter; + private static readonly Action _doneAttemptingToBindParameter; + private static readonly Action _attemptingToBindProperty; + private static readonly Action _doneAttemptingToBindProperty; + private static readonly Action _attemptingToValidateProperty; + 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; @@ -417,35 +442,161 @@ namespace Microsoft.AspNetCore.Mvc.Internal 11, "List of registered output formatters, in the following order: {OutputFormatters}"); - _ifMatchPreconditionFailed = LoggerMessage.Define( - LogLevel.Debug, - 12, - "Current request's If-Match header check failed as the file's current etag '{CurrentETag}' does not match with any of the supplied etags."); - - _ifUnmodifiedSincePreconditionFailed = LoggerMessage.Define( - LogLevel.Debug, - 13, - "Current request's If-Unmodified-Since header check failed as the file was modified (at '{lastModified}') after the If-Unmodified-Since date '{IfUnmodifiedSinceDate}'."); - - _ifRangeLastModifiedPreconditionFailed = LoggerMessage.Define( - LogLevel.Debug, - 14, - "Could not serve range as the file was modified (at {LastModified}) after the if-Range's last modified date '{IfRangeLastModified}'."); - - _ifRangeETagPreconditionFailed = LoggerMessage.Define( - LogLevel.Debug, - 15, - "Could not serve range as the file's current etag '{CurrentETag}' does not match the If-Range etag '{IfRangeETag}'."); - - _notEnabledForRangeProcessing = LoggerMessage.Define( - LogLevel.Debug, - 16, - $"The file result has not been enabled for processing range requests. To enable it, set the property '{nameof(FileResult.EnableRangeProcessing)}' on the result to 'true'."); - _writingRangeToBody = LoggerMessage.Define( LogLevel.Debug, 17, "Writing the requested range of bytes to the body..."); + + _registeredModelBinderProviders = LoggerMessage.Define( + LogLevel.Debug, + 12, + "Registered model binder providers, in the following order: {ModelBinderProviders}"); + + _attemptingToBindPropertyModel = LoggerMessage.Define( + LogLevel.Debug, + 13, + "Attempting to bind property '{PropertyContainerType}.{PropertyName}' of type '{ModelType}' using the name '{ModelName}' in request data ..."); + + _doneAttemptingToBindPropertyModel = LoggerMessage.Define( + LogLevel.Debug, + 14, + "Done attempting to bind property '{PropertyContainerType}.{PropertyName}' of type '{ModelType}'."); + + _foundNoValueForPropertyInRequest = LoggerMessage.Define( + LogLevel.Debug, + 15, + "Could not find a value in the request with name '{ModelName}' for binding property '{PropertyContainerType}.{ModelFieldName}' of type '{ModelType}'."); + + _foundNoValueInRequest = LoggerMessage.Define( + LogLevel.Debug, + 16, + "Could not find a value in the request with name '{ModelName}' for binding parameter '{ModelFieldName}' of type '{ModelType}'."); + + _noPublicSettableProperties = LoggerMessage.Define( + LogLevel.Debug, + 17, + "Could not bind to model with name '{ModelName}' and type '{ModelType}' as the type has no public settable properties."); + + _cannotBindToComplexType = LoggerMessage.Define( + LogLevel.Debug, + 18, + "Could not bind to model of type '{ModelType}' as there were no values in the request for any of the properties."); + + _cannotBindToFilesCollectionDueToUnsupportedContentType = LoggerMessage.Define( + LogLevel.Debug, + 19, + "Could not bind to model with name '{ModelName}' and type '{ModelType}' as the request did not have a content type of either 'application/x-www-form-urlencoded' or 'multipart/form-data'."); + + _cannotCreateHeaderModelBinder = LoggerMessage.Define( + LogLevel.Debug, + 20, + "Could not create a binder for type '{ModelType}' as this binder only supports 'System.String' type or a collection of 'System.String'."); + + _noFilesFoundInRequest = LoggerMessage.Define( + LogLevel.Debug, + 21, + "No files found in the request to bind the model to."); + + _attemptingToBindParameter = LoggerMessage.Define( + LogLevel.Debug, + 22, + "Attempting to bind parameter '{ParameterName}' of type '{ModelType}' ..."); + + _doneAttemptingToBindParameter = LoggerMessage.Define( + LogLevel.Debug, + 23, + "Done attempting to bind parameter '{ParameterName}' of type '{ModelType}'."); + + _attemptingToBindModel = LoggerMessage.Define( + LogLevel.Debug, + 24, + "Attempting to bind model of type '{ModelType}' using the name '{ModelName}' in request data ..."); + + _doneAttemptingToBindModel = LoggerMessage.Define( + LogLevel.Debug, + 25, + "Done attempting to bind model of type '{ModelType}' using the name '{ModelName}'."); + + _attemptingToValidateParameter = LoggerMessage.Define( + LogLevel.Debug, + 26, + "Attempting to validate the bound parameter '{ParameterName}' of type '{ModelType}' ..."); + + _doneAttemptingToValidateParameter = LoggerMessage.Define( + LogLevel.Debug, + 27, + "Done attempting to validate the bound parameter '{ParameterName}' of type '{ModelType}'."); + + _noNonIndexBasedFormatFoundForCollection = LoggerMessage.Define( + LogLevel.Debug, + 28, + "Could not bind to collection using a format like {ModelName}=value1&{ModelName}=value2"); + + _attemptingToBindCollectionUsingIndices = LoggerMessage.Define( + LogLevel.Debug, + 29, + "Attempting to bind model using indices. Example formats include: " + + "[0]=value1&[1]=value2, " + + "{ModelName}[0]=value1&{ModelName}[1]=value2, " + + "{ModelName}.index=zero&{ModelName}.index=one&{ModelName}[zero]=value1&{ModelName}[one]=value2"); + + _attemptingToBindCollectionOfKeyValuePair = LoggerMessage.Define( + LogLevel.Debug, + 30, + "Attempting to bind collection of KeyValuePair. Example formats include: " + + "[0].Key=key1&[0].Value=value1&[1].Key=key2&[1].Value=value2, " + + "{ModelName}[0].Key=key1&{ModelName}[0].Value=value1&{ModelName}[1].Key=key2&{ModelName}[1].Value=value2, " + + "{ModelName}[key1]=value1&{ModelName}[key2]=value2"); + + _noKeyValueFormatForDictionaryModelBinder = LoggerMessage.Define( + LogLevel.Debug, + 33, + "Attempting to bind model with name '{ModelName}' using the format {ModelName}[key1]=value1&{ModelName}[key2]=value2"); + + _ifMatchPreconditionFailed = LoggerMessage.Define( + LogLevel.Debug, + 34, + "Current request's If-Match header check failed as the file's current etag '{CurrentETag}' does not match with any of the supplied etags."); + + _ifUnmodifiedSincePreconditionFailed = LoggerMessage.Define( + LogLevel.Debug, + 35, + "Current request's If-Unmodified-Since header check failed as the file was modified (at '{lastModified}') after the If-Unmodified-Since date '{IfUnmodifiedSinceDate}'."); + + _ifRangeLastModifiedPreconditionFailed = LoggerMessage.Define( + LogLevel.Debug, + 36, + "Could not serve range as the file was modified (at {LastModified}) after the if-Range's last modified date '{IfRangeLastModified}'."); + + _ifRangeETagPreconditionFailed = LoggerMessage.Define( + LogLevel.Debug, + 37, + "Could not serve range as the file's current etag '{CurrentETag}' does not match the If-Range etag '{IfRangeETag}'."); + + _notEnabledForRangeProcessing = LoggerMessage.Define( + LogLevel.Debug, + 38, + $"The file result has not been enabled for processing range requests. To enable it, set the property '{nameof(FileResult.EnableRangeProcessing)}' on the result to 'true'."); + + _attemptingToBindProperty = LoggerMessage.Define( + LogLevel.Debug, + 39, + "Attempting to bind property '{PropertyContainerType}.{PropertyName}' of type '{ModelType}' ..."); + + _doneAttemptingToBindProperty = LoggerMessage.Define( + LogLevel.Debug, + 40, + "Done attempting to bind property '{PropertyContainerType}.{PropertyName}' of type '{ModelType}'."); + + _attemptingToValidateProperty = LoggerMessage.Define( + LogLevel.Debug, + 41, + "Attempting to validate the bound property '{PropertyContainerType}.{PropertyName}' of type '{ModelType}' ..."); + + _doneAttemptingToValidateProperty = LoggerMessage.Define( + LogLevel.Debug, + 42, + "Done attempting to validate the bound property '{PropertyContainerType}.{PropertyName}' of type '{ModelType}'."); } public static void RegisteredOutputFormatters(this ILogger logger, IEnumerable outputFormatters) @@ -967,6 +1118,200 @@ namespace Microsoft.AspNetCore.Mvc.Internal _ifRangeETagPreconditionFailed(logger, currentETag, ifRangeTag, null); } + public static void RegisteredModelBinderProviders(this ILogger logger, IModelBinderProvider[] providers) + { + _registeredModelBinderProviders(logger, providers, null); + } + + public static void FoundNoValueInRequest(this ILogger logger, ModelBindingContext bindingContext) + { + if (!logger.IsEnabled(LogLevel.Debug)) + { + return; + } + + var modelMetadata = bindingContext.ModelMetadata; + var isProperty = modelMetadata.ContainerType != null; + + if (isProperty) + { + _foundNoValueForPropertyInRequest( + logger, + bindingContext.ModelName, + modelMetadata.ContainerType, + modelMetadata.PropertyName, + bindingContext.ModelType, + null); + } + else + { + _foundNoValueInRequest( + logger, + bindingContext.ModelName, + modelMetadata.PropertyName, + bindingContext.ModelType, + null); + } + } + + public static void NoPublicSettableProperties(this ILogger logger, ModelBindingContext bindingContext) + { + _noPublicSettableProperties(logger, bindingContext.ModelName, bindingContext.ModelType, null); + } + + public static void CannotBindToComplexType(this ILogger logger, ModelBindingContext bindingContext) + { + _cannotBindToComplexType(logger, bindingContext.ModelType, null); + } + + public static void CannotBindToFilesCollectionDueToUnsupportedContentType(this ILogger logger, ModelBindingContext bindingContext) + { + _cannotBindToFilesCollectionDueToUnsupportedContentType(logger, bindingContext.ModelName, bindingContext.ModelType, null); + } + + public static void CannotCreateHeaderModelBinder(this ILogger logger, Type modelType) + { + _cannotCreateHeaderModelBinder(logger, modelType, null); + } + + public static void NoFilesFoundInRequest(this ILogger logger) + { + _noFilesFoundInRequest(logger, null); + } + + public static void AttemptingToBindModel(this ILogger logger, ModelBindingContext bindingContext) + { + if (!logger.IsEnabled(LogLevel.Debug)) + { + return; + } + + var modelMetadata = bindingContext.ModelMetadata; + var isProperty = modelMetadata.ContainerType != null; + + if (isProperty) + { + _attemptingToBindPropertyModel( + logger, + modelMetadata.ContainerType, + modelMetadata.PropertyName, + modelMetadata.ModelType, + bindingContext.ModelName, + null); + } + else + { + _attemptingToBindModel(logger, bindingContext.ModelType, bindingContext.ModelName, null); + } + } + + public static void DoneAttemptingToBindModel(this ILogger logger, ModelBindingContext bindingContext) + { + var modelMetadata = bindingContext.ModelMetadata; + var isProperty = modelMetadata.ContainerType != null; + + if (isProperty) + { + _doneAttemptingToBindPropertyModel( + logger, + modelMetadata.ContainerType, + modelMetadata.PropertyName, + modelMetadata.ModelType, + null); + } + else + { + _doneAttemptingToBindModel(logger, bindingContext.ModelType, bindingContext.ModelName, null); + } + } + + public static void AttemptingToBindParameterOrProperty(this ILogger logger, ParameterDescriptor parameter, ModelBindingContext bindingContext) + { + if (parameter is ControllerBoundPropertyDescriptor propertyDescriptor) + { + _attemptingToBindProperty(logger, propertyDescriptor.PropertyInfo.DeclaringType, parameter.Name, bindingContext.ModelType, null); + } + else + { + _attemptingToBindParameter(logger, parameter.Name, bindingContext.ModelType, null); + } + } + + public static void DoneAttemptingToBindParameterOrProperty(this ILogger logger, ParameterDescriptor parameter, ModelBindingContext bindingContext) + { + if (parameter is ControllerBoundPropertyDescriptor propertyDescriptor) + { + _doneAttemptingToBindProperty(logger, propertyDescriptor.PropertyInfo.DeclaringType, parameter.Name, bindingContext.ModelType, null); + } + else + { + _doneAttemptingToBindParameter(logger, parameter.Name, bindingContext.ModelType, null); + } + } + + public static void AttemptingToValidateParameterOrProperty(this ILogger logger, ParameterDescriptor parameter, ModelBindingContext bindingContext) + { + if (parameter is ControllerBoundPropertyDescriptor propertyDescriptor) + { + _attemptingToValidateProperty(logger, propertyDescriptor.PropertyInfo.DeclaringType, parameter.Name, bindingContext.ModelType, null); + } + else + { + _attemptingToValidateParameter(logger, parameter.Name, bindingContext.ModelType, null); + } + } + + public static void DoneAttemptingToValidateParameterOrProperty(this ILogger logger, ParameterDescriptor parameter, ModelBindingContext bindingContext) + { + if (parameter is ControllerBoundPropertyDescriptor propertyDescriptor) + { + _doneAttemptingToValidateProperty(logger, propertyDescriptor.PropertyInfo.DeclaringType, parameter.Name, bindingContext.ModelType, null); + } + else + { + _doneAttemptingToValidateParameter(logger, parameter.Name, bindingContext.ModelType, null); + } + } + + public static void NoNonIndexBasedFormatFoundForCollection(this ILogger logger, ModelBindingContext bindingContext) + { + var modelName = bindingContext.ModelName; + _noNonIndexBasedFormatFoundForCollection(logger, modelName, modelName, null); + } + + public static void AttemptingToBindCollectionUsingIndices(this ILogger logger, ModelBindingContext bindingContext) + { + if (!logger.IsEnabled(LogLevel.Debug)) + { + return; + } + + var modelName = bindingContext.ModelName; + + var enumerableType = ClosedGenericMatcher.ExtractGenericInterface(bindingContext.ModelType, typeof(IEnumerable<>)); + if (enumerableType != null) + { + var elementType = enumerableType.GenericTypeArguments[0]; + if (elementType.IsGenericType && elementType.GetGenericTypeDefinition().GetTypeInfo() == typeof(KeyValuePair<,>).GetTypeInfo()) + { + _attemptingToBindCollectionOfKeyValuePair(logger, modelName, modelName, modelName, modelName, modelName, modelName, null); + return; + } + } + + _attemptingToBindCollectionUsingIndices(logger, modelName, modelName, modelName, modelName, modelName, modelName, null); + } + + public static void NoKeyValueFormatForDictionaryModelBinder(this ILogger logger, ModelBindingContext bindingContext) + { + _noKeyValueFormatForDictionaryModelBinder( + logger, + bindingContext.ModelName, + bindingContext.ModelName, + bindingContext.ModelName, + null); + } + private static void LogFilterExecutionPlan( ILogger logger, string filterType, diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs index e898cd6b1f..d33813cd1e 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Mvc.Internal @@ -23,8 +24,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal private readonly IHttpRequestStreamReaderFactory _readerFactory; private readonly ILoggerFactory _loggerFactory; + // Used in tests public MvcCoreMvcOptionsSetup(IHttpRequestStreamReaderFactory readerFactory) - : this(readerFactory, loggerFactory: null) + : this(readerFactory, NullLoggerFactory.Instance) { } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Microsoft.AspNetCore.Mvc.Core.csproj b/src/Microsoft.AspNetCore.Mvc.Core/Microsoft.AspNetCore.Mvc.Core.csproj index b753fbd806..5861db1584 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Microsoft.AspNetCore.Mvc.Core.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Core/Microsoft.AspNetCore.Mvc.Core.csproj @@ -28,6 +28,7 @@ Microsoft.AspNetCore.Mvc.RouteAttribute + diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs index c88625f490..96c6a31288 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs @@ -5,6 +5,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -14,14 +16,30 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// Type of elements in the array. public class ArrayModelBinder : CollectionModelBinder { + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Creates a new . + /// + /// + /// The for binding . + /// + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] + public ArrayModelBinder(IModelBinder elementBinder) + : this(elementBinder, NullLoggerFactory.Instance) + { + } + /// /// Creates a new . /// /// /// The for binding . /// - public ArrayModelBinder(IModelBinder elementBinder) - : base(elementBinder) + /// The . + public ArrayModelBinder(IModelBinder elementBinder, ILoggerFactory loggerFactory) + : base(elementBinder, loggerFactory) { } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinderProvider.cs index 33267fd069..190390b9c7 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinderProvider.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -24,7 +26,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var elementBinder = context.CreateBinder(context.Metadata.ElementMetadata); var binderType = typeof(ArrayModelBinder<>).MakeGenericType(elementType); - return (IModelBinder)Activator.CreateInstance(binderType, elementBinder); + var loggerFactory = context.Services.GetRequiredService(); + return (IModelBinder)Activator.CreateInstance(binderType, elementBinder, loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs index f33deed4cc..8e0744cfda 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs @@ -100,6 +100,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger?.AttemptingToBindModel(bindingContext); + // Special logic for body, treat the model name as string.Empty for the top level // object, but allow an override via BinderModelName. The purpose of this is to try // and be similar to the behavior for POCOs bound via traditional model binding. @@ -147,6 +149,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var message = Resources.FormatUnsupportedContentType(httpContext.Request.ContentType); var exception = new UnsupportedContentTypeException(message); bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata); + _logger?.DoneAttemptingToBindModel(bindingContext); return; } @@ -157,6 +160,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (result.HasError) { // Formatter encountered an error. Do not use the model it returned. + _logger?.DoneAttemptingToBindModel(bindingContext); return; } @@ -183,6 +187,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata); } + + _logger?.DoneAttemptingToBindModel(bindingContext); } private bool ShouldHandleException(IInputFormatter formatter) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ByteArrayModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ByteArrayModelBinder.cs index ff7b81704f..99461f9ec9 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ByteArrayModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ByteArrayModelBinder.cs @@ -3,6 +3,9 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -11,6 +14,34 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// public class ByteArrayModelBinder : IModelBinder { + private readonly ILogger _logger; + + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that takes an . + /// Initializes a new instance of . + /// + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that takes an " + nameof(ILoggerFactory) + ".")] + public ByteArrayModelBinder() + : this(NullLoggerFactory.Instance) + { + } + + /// + /// Initializes a new instance of . + /// + /// The . + public ByteArrayModelBinder(ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + _logger = loggerFactory.CreateLogger(); + } + /// public Task BindModelAsync(ModelBindingContext bindingContext) { @@ -19,10 +50,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger.AttemptingToBindModel(bindingContext); + // Check for missing data case 1: There was no element containing this data. var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == ValueProviderResult.None) { + _logger.FoundNoValueInRequest(bindingContext); + _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } @@ -32,6 +67,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var value = valueProviderResult.FirstValue; if (string.IsNullOrEmpty(value)) { + _logger.FoundNoValueInRequest(bindingContext); + _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } @@ -39,7 +76,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { var model = Convert.FromBase64String(value); bindingContext.Result = ModelBindingResult.Success(model); - return Task.CompletedTask; } catch (Exception exception) { @@ -47,8 +83,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.ModelName, exception, bindingContext.ModelMetadata); - return Task.CompletedTask; } + + _logger.DoneAttemptingToBindModel(bindingContext); + return Task.CompletedTask; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ByteArrayModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ByteArrayModelBinderProvider.cs index 1253b44705..402f796640 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ByteArrayModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ByteArrayModelBinderProvider.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -20,7 +22,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (context.Metadata.ModelType == typeof(byte[])) { - return new ByteArrayModelBinder(); + var loggerFactory = context.Services.GetRequiredService(); + return new ByteArrayModelBinder(loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs index 2e551e5867..d219519e4f 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs @@ -12,6 +12,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -23,18 +25,38 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { private Func _modelCreator; + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Creates a new . + /// + /// The for binding elements. + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] + public CollectionModelBinder(IModelBinder elementBinder) + : this(elementBinder, NullLoggerFactory.Instance) + { + } + /// /// Creates a new . /// /// The for binding elements. - public CollectionModelBinder(IModelBinder elementBinder) + /// The . + public CollectionModelBinder(IModelBinder elementBinder, ILoggerFactory loggerFactory) { if (elementBinder == null) { throw new ArgumentNullException(nameof(elementBinder)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + ElementBinder = elementBinder; + Logger = loggerFactory.CreateLogger(GetType()); } /// @@ -42,6 +64,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// protected IModelBinder ElementBinder { get; } + /// + /// The used for logging in this binder. + /// + protected ILogger Logger { get; } + /// public virtual async Task BindModelAsync(ModelBindingContext bindingContext) { @@ -50,9 +77,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + Logger.AttemptingToBindModel(bindingContext); + var model = bindingContext.Model; if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) { + Logger.FoundNoValueInRequest(bindingContext); + // If we failed to find data for a top-level model, then generate a // default 'empty' model (or use existing Model) and return it. if (bindingContext.IsTopLevelObject) @@ -65,6 +96,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.Result = ModelBindingResult.Success(model); } + Logger.DoneAttemptingToBindModel(bindingContext); return; } @@ -73,6 +105,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders CollectionResult result; if (valueProviderResult == ValueProviderResult.None) { + Logger.NoNonIndexBasedFormatFoundForCollection(bindingContext); result = await BindComplexCollection(bindingContext); } else @@ -110,6 +143,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } bindingContext.Result = ModelBindingResult.Success(model); + Logger.DoneAttemptingToBindModel(bindingContext); } /// @@ -207,6 +241,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Used when the ValueProvider contains the collection to be bound as multiple elements, e.g. foo[0], foo[1]. private Task BindComplexCollection(ModelBindingContext bindingContext) { + Logger.AttemptingToBindCollectionUsingIndices(bindingContext); + var indexPropertyName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, "index"); var valueProviderResultIndex = bindingContext.ValueProvider.GetValue(indexPropertyName); var indexNames = GetIndexNamesFromValueProviderResult(valueProviderResultIndex); @@ -273,7 +309,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // If we're working with a fixed set of indexes then this is the format like: // - // ?parameter.index=zero,one,two¶meter[zero]=0&¶meter[one]=1¶meter[two]=2... + // ?parameter.index=zero¶meter.index=one¶meter.index=two¶meter[zero]=0¶meter[one]=1¶meter[two]=2... // // We need to provide this data to the validation system so it can 'replay' the keys. // But we can't just set ValidationState here, because it needs the 'real' model. diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinderProvider.cs index cb80107ff3..0617122b5f 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinderProvider.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using System.Reflection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -29,6 +31,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders return null; } + var loggerFactory = context.Services.GetRequiredService(); + // If the model type is ICollection<> then we can call its Add method, so we can always support it. var collectionType = ClosedGenericMatcher.ExtractGenericInterface(modelType, typeof(ICollection<>)); if (collectionType != null) @@ -37,7 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var elementBinder = context.CreateBinder(context.MetadataProvider.GetMetadataForType(elementType)); var binderType = typeof(CollectionModelBinder<>).MakeGenericType(collectionType.GenericTypeArguments); - return (IModelBinder)Activator.CreateInstance(binderType, elementBinder); + return (IModelBinder)Activator.CreateInstance(binderType, elementBinder, loggerFactory); } // If the model type is IEnumerable<> then we need to know if we can assign a List<> to it, since @@ -53,7 +57,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var elementBinder = context.CreateBinder(context.MetadataProvider.GetMetadataForType(elementType)); var binderType = typeof(CollectionModelBinder<>).MakeGenericType(enumerableType.GenericTypeArguments); - return (IModelBinder)Activator.CreateInstance(binderType, elementBinder); + return (IModelBinder)Activator.CreateInstance(binderType, elementBinder, loggerFactory); } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs index b59cd6e9bf..55a5e41055 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs @@ -7,6 +7,9 @@ using System.Linq.Expressions; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Core; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -16,22 +19,47 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public class ComplexTypeModelBinder : IModelBinder { private readonly IDictionary _propertyBinders; + private readonly ILogger _logger; private Func _modelCreator; + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Creates a new . + /// + /// + /// The of binders to use for binding properties. + /// + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] + public ComplexTypeModelBinder(IDictionary propertyBinders) + : this(propertyBinders, NullLoggerFactory.Instance) + { + } + /// /// Creates a new . /// /// /// The of binders to use for binding properties. /// - public ComplexTypeModelBinder(IDictionary propertyBinders) + /// The . + public ComplexTypeModelBinder( + IDictionary propertyBinders, + ILoggerFactory loggerFactory) { if (propertyBinders == null) { throw new ArgumentNullException(nameof(propertyBinders)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _propertyBinders = propertyBinders; + _logger = loggerFactory.CreateLogger(); } /// @@ -42,6 +70,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger.AttemptingToBindModel(bindingContext); + if (!CanCreateModel(bindingContext)) { return Task.CompletedTask; @@ -106,6 +136,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } bindingContext.Result = ModelBindingResult.Success(bindingContext.Model); + _logger.DoneAttemptingToBindModel(bindingContext); } /// @@ -199,6 +230,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // level object. So we return false. if (bindingContext.ModelMetadata.Properties.Count == 0) { + _logger.NoPublicSettableProperties(bindingContext); return false; } @@ -272,6 +304,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders return true; } + _logger.CannotBindToComplexType(bindingContext); + return false; } @@ -307,7 +341,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders return true; } - /// /// Creates suitable for given . /// diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinderProvider.cs index fc1286468b..f0d6b5989c 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinderProvider.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -28,7 +30,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders propertyBinders.Add(property, context.CreateBinder(property)); } - return new ComplexTypeModelBinder(propertyBinders); + var loggerFactory = context.Services.GetRequiredService(); + return new ComplexTypeModelBinder(propertyBinders, loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DecimalModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DecimalModelBinder.cs index 0c9b2e58c9..7692baa009 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DecimalModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DecimalModelBinder.cs @@ -5,6 +5,9 @@ using System; using System.Globalization; using System.Runtime.ExceptionServices; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -15,10 +18,35 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public class DecimalModelBinder : IModelBinder { private readonly NumberStyles _supportedStyles; + private readonly ILogger _logger; + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Initializes a new instance of . + /// + /// The . + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] public DecimalModelBinder(NumberStyles supportedStyles) + : this(supportedStyles, NullLoggerFactory.Instance) { + } + + /// + /// Initializes a new instance of . + /// + /// The . + /// The . + public DecimalModelBinder(NumberStyles supportedStyles, ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _supportedStyles = supportedStyles; + _logger = loggerFactory.CreateLogger(); } /// @@ -29,11 +57,16 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger.AttemptingToBindModel(bindingContext); + var modelName = bindingContext.ModelName; var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); if (valueProviderResult == ValueProviderResult.None) { + _logger.FoundNoValueInRequest(bindingContext); + // no entry + _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } @@ -72,13 +105,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders modelName, metadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor( valueProviderResult.ToString())); - - return Task.CompletedTask; } else { bindingContext.Result = ModelBindingResult.Success(model); - return Task.CompletedTask; } } catch (Exception exception) @@ -94,8 +124,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders modelState.TryAddModelError(modelName, exception, metadata); // Conversion failed. - return Task.CompletedTask; } + + _logger.DoneAttemptingToBindModel(bindingContext); + return Task.CompletedTask; } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs index d3520125c6..dc967fefdf 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs @@ -9,6 +9,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -21,13 +23,28 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { private readonly IModelBinder _valueBinder; + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Creates a new . + /// + /// The for . + /// The for . + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] + public DictionaryModelBinder(IModelBinder keyBinder, IModelBinder valueBinder) + : this(keyBinder, valueBinder, NullLoggerFactory.Instance) + { + } + /// /// Creates a new . /// /// The for . /// The for . - public DictionaryModelBinder(IModelBinder keyBinder, IModelBinder valueBinder) - : base(new KeyValuePairModelBinder(keyBinder, valueBinder)) + /// The . + public DictionaryModelBinder(IModelBinder keyBinder, IModelBinder valueBinder, ILoggerFactory loggerFactory) + : base(new KeyValuePairModelBinder(keyBinder, valueBinder, loggerFactory), loggerFactory) { if (valueBinder == null) { @@ -62,6 +79,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders return; } + Logger.NoKeyValueFormatForDictionaryModelBinder(bindingContext); + var enumerableValueProvider = bindingContext.ValueProvider as IEnumerableValueProvider; if (enumerableValueProvider == null) { diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinderProvider.cs index 87166f8cb8..0d7db7c064 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinderProvider.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -31,7 +33,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var valueBinder = context.CreateBinder(context.MetadataProvider.GetMetadataForType(valueType)); var binderType = typeof(DictionaryModelBinder<,>).MakeGenericType(dictionaryType.GenericTypeArguments); - return (IModelBinder)Activator.CreateInstance(binderType, keyBinder, valueBinder); + var loggerFactory = context.Services.GetRequiredService(); + return (IModelBinder)Activator.CreateInstance(binderType, keyBinder, valueBinder, loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DoubleModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DoubleModelBinder.cs index c09d7cf0ec..77d32d5a0d 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DoubleModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DoubleModelBinder.cs @@ -5,6 +5,9 @@ using System; using System.Globalization; using System.Runtime.ExceptionServices; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -15,10 +18,35 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public class DoubleModelBinder : IModelBinder { private readonly NumberStyles _supportedStyles; + private readonly ILogger _logger; + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Initializes a new instance of . + /// + /// The . + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] public DoubleModelBinder(NumberStyles supportedStyles) + : this(supportedStyles, NullLoggerFactory.Instance) { + } + + /// + /// Initializes a new instance of . + /// + /// The . + /// The . + public DoubleModelBinder(NumberStyles supportedStyles, ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _supportedStyles = supportedStyles; + _logger = loggerFactory.CreateLogger(); } /// @@ -29,11 +57,16 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger.AttemptingToBindModel(bindingContext); + var modelName = bindingContext.ModelName; var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); if (valueProviderResult == ValueProviderResult.None) { + _logger.FoundNoValueInRequest(bindingContext); + // no entry + _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } @@ -72,13 +105,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders modelName, metadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor( valueProviderResult.ToString())); - - return Task.CompletedTask; } else { bindingContext.Result = ModelBindingResult.Success(model); - return Task.CompletedTask; } } catch (Exception exception) @@ -94,8 +124,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders modelState.TryAddModelError(modelName, exception, metadata); // Conversion failed. - return Task.CompletedTask; } + + _logger.DoneAttemptingToBindModel(bindingContext); + return Task.CompletedTask; } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinder.cs index 6348b5f11c..8489bc5ed0 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinder.cs @@ -3,6 +3,7 @@ using System; using System.Globalization; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -13,15 +14,31 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { private readonly bool _suppressBindingUndefinedValueToEnumType; - public EnumTypeModelBinder(bool supressBindingUndefinedValueToEnumType, Type modelType) - : base(modelType) + /// + /// Initializes a new instance of . + /// + /// + /// Flag to determine if binding to undefined should be suppressed or not. + /// + /// The mdoel type. + /// The , + public EnumTypeModelBinder( + bool suppressBindingUndefinedValueToEnumType, + Type modelType, + ILoggerFactory loggerFactory) + : base(modelType, loggerFactory) { if (modelType == null) { throw new ArgumentNullException(nameof(modelType)); } - _suppressBindingUndefinedValueToEnumType = supressBindingUndefinedValueToEnumType; + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + _suppressBindingUndefinedValueToEnumType = suppressBindingUndefinedValueToEnumType; } protected override void CheckModel( diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinderProvider.cs index 140913a1bb..cd75fbb2fe 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinderProvider.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -12,6 +14,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { private readonly MvcOptions _options; + /// + /// Initializes a new instance of . + /// + /// The . public EnumTypeModelBinderProvider(MvcOptions options) { _options = options; @@ -27,9 +33,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (context.Metadata.IsEnum) { + var loggerFactory = context.Services.GetRequiredService(); return new EnumTypeModelBinder( _options.SuppressBindingUndefinedValueToEnumType, - context.Metadata.UnderlyingOrModelType); + context.Metadata.UnderlyingOrModelType, + loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FloatModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FloatModelBinder.cs index 370b1a692a..515266d2df 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FloatModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FloatModelBinder.cs @@ -5,6 +5,9 @@ using System; using System.Globalization; using System.Runtime.ExceptionServices; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -15,10 +18,35 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public class FloatModelBinder : IModelBinder { private readonly NumberStyles _supportedStyles; + private readonly ILogger _logger; + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Initializes a new instance of . + /// + /// The . + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] public FloatModelBinder(NumberStyles supportedStyles) + : this(supportedStyles, NullLoggerFactory.Instance) { + } + + /// + /// Initializes a new instance of . + /// + /// The . + /// The . + public FloatModelBinder(NumberStyles supportedStyles, ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _supportedStyles = supportedStyles; + _logger = loggerFactory.CreateLogger(); } /// @@ -29,11 +57,16 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger.AttemptingToBindModel(bindingContext); + var modelName = bindingContext.ModelName; var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); if (valueProviderResult == ValueProviderResult.None) { + _logger.FoundNoValueInRequest(bindingContext); + // no entry + _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } @@ -72,13 +105,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders modelName, metadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor( valueProviderResult.ToString())); - - return Task.CompletedTask; } else { bindingContext.Result = ModelBindingResult.Success(model); - return Task.CompletedTask; } } catch (Exception exception) @@ -94,8 +124,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders modelState.TryAddModelError(modelName, exception, metadata); // Conversion failed. - return Task.CompletedTask; } + + _logger.DoneAttemptingToBindModel(bindingContext); + return Task.CompletedTask; } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FloatingPointTypeModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FloatingPointTypeModelBinderProvider.cs index 438bde541d..b881f66235 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FloatingPointTypeModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FloatingPointTypeModelBinderProvider.cs @@ -3,6 +3,8 @@ using System; using System.Globalization; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -25,19 +27,20 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } var modelType = context.Metadata.UnderlyingOrModelType; + var loggerFactory = context.Services.GetRequiredService(); if (modelType == typeof(decimal)) { - return new DecimalModelBinder(SupportedStyles); + return new DecimalModelBinder(SupportedStyles, loggerFactory); } if (modelType == typeof(double)) { - return new DoubleModelBinder(SupportedStyles); + return new DoubleModelBinder(SupportedStyles, loggerFactory); } if (modelType == typeof(float)) { - return new FloatModelBinder(SupportedStyles); + return new FloatModelBinder(SupportedStyles, loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinder.cs index 2688f11d08..41d96ed272 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinder.cs @@ -7,6 +7,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders @@ -16,6 +19,34 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// public class FormCollectionModelBinder : IModelBinder { + private readonly ILogger _logger; + + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that takes an . + /// Initializes a new instance of . + /// + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that takes an " + nameof(ILoggerFactory) + ".")] + public FormCollectionModelBinder() + : this(NullLoggerFactory.Instance) + { + } + + /// + /// Initializes a new instance of . + /// + /// The . + public FormCollectionModelBinder(ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + _logger = loggerFactory.CreateLogger(); + } + /// public async Task BindModelAsync(ModelBindingContext bindingContext) { @@ -24,6 +55,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger.AttemptingToBindModel(bindingContext); + object model; var request = bindingContext.HttpContext.Request; if (request.HasFormContentType) @@ -33,10 +66,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } else { + _logger.CannotBindToFilesCollectionDueToUnsupportedContentType(bindingContext); model = new EmptyFormCollection(); } bindingContext.Result = ModelBindingResult.Success(model); + _logger.DoneAttemptingToBindModel(bindingContext); } private class EmptyFormCollection : IFormCollection diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinderProvider.cs index 2e884815f9..edc91adfaf 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinderProvider.cs @@ -5,6 +5,8 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Core; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -34,7 +36,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (modelType == typeof(IFormCollection)) { - return new FormCollectionModelBinder(); + var loggerFactory = context.Services.GetRequiredService(); + return new FormCollectionModelBinder(loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinder.cs index 350097b7e8..5a7f1157ac 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinder.cs @@ -8,8 +8,11 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -18,6 +21,34 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// public class FormFileModelBinder : IModelBinder { + private readonly ILogger _logger; + + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that takes an . + /// Initializes a new instance of . + /// + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that takes an " + nameof(ILoggerFactory) + ".")] + public FormFileModelBinder() + : this(NullLoggerFactory.Instance) + { + } + + /// + /// Initializes a new instance of . + /// + /// The . + public FormFileModelBinder(ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + _logger = loggerFactory.CreateLogger(); + } + /// public async Task BindModelAsync(ModelBindingContext bindingContext) { @@ -26,6 +57,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger.AttemptingToBindModel(bindingContext); + var createFileCollection = bindingContext.ModelType == typeof(IFormFileCollection); if (!createFileCollection && !ModelBindingHelper.CanGetCompatibleCollection(bindingContext)) { @@ -58,6 +91,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (postedFiles.Count == 0) { // Silently fail if the named file does not exist in the request. + _logger.DoneAttemptingToBindModel(bindingContext); return; } @@ -69,6 +103,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // Silently fail if no files match. Will bind to an empty collection (treat empty as a success // case and not reach here) if binding to a top-level object. + _logger.DoneAttemptingToBindModel(bindingContext); return; } @@ -103,6 +138,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders attemptedValue: null); bindingContext.Result = ModelBindingResult.Success(value); + _logger.DoneAttemptingToBindModel(bindingContext); } private async Task GetFormFilesAsync( @@ -128,6 +164,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders postedFiles.Add(file); } } + + if (postedFiles.Count == 0) + { + _logger.NoFilesFoundInRequest(); + } + } + else + { + _logger.CannotBindToFilesCollectionDueToUnsupportedContentType(bindingContext); } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinderProvider.cs index 3d1510a7d9..2edd550fed 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinderProvider.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -27,7 +29,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders modelType == typeof(IFormFileCollection) || typeof(IEnumerable).IsAssignableFrom(modelType)) { - return new FormFileModelBinder(); + var loggerFactory = context.Services.GetRequiredService(); + return new FormFileModelBinder(loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs index ad13e09a50..5be7fceedc 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs @@ -4,7 +4,10 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -14,6 +17,34 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// public class HeaderModelBinder : IModelBinder { + private readonly ILogger _logger; + + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that takes an . + /// Initializes a new instance of . + /// + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that takes an " + nameof(ILoggerFactory) + ".")] + public HeaderModelBinder() + : this(NullLoggerFactory.Instance) + { + } + + /// + /// Initializes a new instance of . + /// + /// The . + public HeaderModelBinder(ILoggerFactory loggerFactory) + { + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + _logger = loggerFactory.CreateLogger(); + } + /// public Task BindModelAsync(ModelBindingContext bindingContext) { @@ -27,6 +58,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Property name can be null if the model metadata represents a type (rather than a property or parameter). var headerName = bindingContext.FieldName; + _logger.AttemptingToBindModel(bindingContext); + + if (!request.Headers.ContainsKey(headerName)) + { + _logger.FoundNoValueInRequest(bindingContext); + } + object model; if (bindingContext.ModelType == typeof(string)) { @@ -62,6 +100,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.Result = ModelBindingResult.Success(model); } + _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinderProvider.cs index ce10e5ebb8..adefc620c6 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinderProvider.cs @@ -2,6 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -21,12 +24,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (context.BindingInfo.BindingSource != null && context.BindingInfo.BindingSource.CanAcceptDataFrom(BindingSource.Header)) { + var loggerFactory = context.Services.GetRequiredService(); + var logger = loggerFactory.CreateLogger(); + // We only support strings and collections of strings. Some cases can fail // at runtime due to collections we can't modify. if (context.Metadata.ModelType == typeof(string) || context.Metadata.ElementType == typeof(string)) { - return new HeaderModelBinder(); + return new HeaderModelBinder(loggerFactory); + } + else + { + logger.CannotCreateHeaderModelBinder(context.Metadata.ModelType); } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinder.cs index 715c8892df..ee90c3f01e 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinder.cs @@ -4,7 +4,10 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -17,13 +20,29 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { private readonly IModelBinder _keyBinder; private readonly IModelBinder _valueBinder; + private readonly ILogger _logger; + + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Creates a new . + /// + /// The for . + /// The for . + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] + public KeyValuePairModelBinder(IModelBinder keyBinder, IModelBinder valueBinder) + : this(keyBinder, valueBinder, NullLoggerFactory.Instance) + { + } /// /// Creates a new . /// /// The for . /// The for . - public KeyValuePairModelBinder(IModelBinder keyBinder, IModelBinder valueBinder) + /// The . + public KeyValuePairModelBinder(IModelBinder keyBinder, IModelBinder valueBinder, ILoggerFactory loggerFactory) { if (keyBinder == null) { @@ -35,8 +54,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(valueBinder)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _keyBinder = keyBinder; _valueBinder = valueBinder; + _logger = loggerFactory.CreateLogger>(); } /// @@ -47,6 +72,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(bindingContext)); } + _logger.AttemptingToBindModel(bindingContext); + var keyModelName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, "Key"); var keyResult = await TryBindStrongModel(bindingContext, _keyBinder, "Key", keyModelName); @@ -60,6 +87,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders ModelBindingHelper.CastOrDefault(valueResult.Model)); bindingContext.Result = ModelBindingResult.Success(model); + _logger.DoneAttemptingToBindModel(bindingContext); return; } @@ -68,6 +96,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.ModelState.TryAddModelError( keyModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.MissingKeyOrValueAccessor()); + _logger.DoneAttemptingToBindModel(bindingContext); return; } @@ -76,6 +105,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.ModelState.TryAddModelError( valueModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.MissingKeyOrValueAccessor()); + _logger.DoneAttemptingToBindModel(bindingContext); return; } @@ -86,6 +116,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var model = new KeyValuePair(); bindingContext.Result = ModelBindingResult.Success(model); } + _logger.DoneAttemptingToBindModel(bindingContext); } internal async Task TryBindStrongModel( diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinderProvider.cs index fb9e706b8a..e17f5d0ab9 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinderProvider.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Reflection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -21,7 +23,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } var modelTypeInfo = context.Metadata.ModelType.GetTypeInfo(); - if (modelTypeInfo.IsGenericType && + if (modelTypeInfo.IsGenericType && modelTypeInfo.GetGenericTypeDefinition().GetTypeInfo() == typeof(KeyValuePair<,>).GetTypeInfo()) { var typeArguments = modelTypeInfo.GenericTypeArguments; @@ -33,7 +35,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var valueBinder = context.CreateBinder(valueMetadata); var binderType = typeof(KeyValuePairModelBinder<,>).MakeGenericType(typeArguments); - return (IModelBinder)Activator.CreateInstance(binderType, keyBinder, valueBinder); + var loggerFactory = context.Services.GetRequiredService(); + return (IModelBinder)Activator.CreateInstance(binderType, keyBinder, valueBinder, loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinder.cs index 74abfada0e..017049e769 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinder.cs @@ -5,6 +5,9 @@ using System; using System.ComponentModel; using System.Runtime.ExceptionServices; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -14,15 +17,40 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public class SimpleTypeModelBinder : IModelBinder { private readonly TypeConverter _typeConverter; + private readonly ILogger _logger; + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Initializes a new instance of . + /// + /// The type to create binder for. + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] public SimpleTypeModelBinder(Type type) + : this(type, NullLoggerFactory.Instance) + { + } + + /// + /// Initializes a new instance of . + /// + /// The type to create binder for. + /// The . + public SimpleTypeModelBinder(Type type, ILoggerFactory loggerFactory) { if (type == null) { throw new ArgumentNullException(nameof(type)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _typeConverter = TypeDescriptor.GetConverter(type); + _logger = loggerFactory.CreateLogger(); } /// @@ -36,10 +64,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == ValueProviderResult.None) { + _logger.FoundNoValueInRequest(bindingContext); + // no entry + _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } + _logger.AttemptingToBindModel(bindingContext); + bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); try @@ -74,6 +107,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders CheckModel(bindingContext, valueProviderResult, model); + _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } catch (Exception exception) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinderProvider.cs index 0a1bcfa7f4..f7d69e016c 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/SimpleTypeModelBinderProvider.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -20,7 +22,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (!context.Metadata.IsComplexType) { - return new SimpleTypeModelBinder(context.Metadata.ModelType); + var loggerFactory = context.Services.GetRequiredService(); + return new SimpleTypeModelBinder(context.Metadata.ModelType, loggerFactory); } return null; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBinderFactory.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBinderFactory.cs index 8388fedafb..e21d62dac1 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBinderFactory.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBinderFactory.cs @@ -10,7 +10,10 @@ using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Mvc.ModelBinding @@ -22,20 +25,42 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding { private readonly IModelMetadataProvider _metadataProvider; private readonly IModelBinderProvider[] _providers; - private readonly ConcurrentDictionary _cache; + private readonly IServiceProvider _serviceProvider; + + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Creates a new . + /// + /// The . + /// The for . + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(IServiceProvider) + ".")] + public ModelBinderFactory(IModelMetadataProvider metadataProvider, IOptions options) + : this(metadataProvider, options, GetDefaultServices()) + { + } /// /// Creates a new . /// /// The . /// The for . - public ModelBinderFactory(IModelMetadataProvider metadataProvider, IOptions options) + /// The . + public ModelBinderFactory( + IModelMetadataProvider metadataProvider, + IOptions options, + IServiceProvider serviceProvider) { _metadataProvider = metadataProvider; _providers = options.Value.ModelBinderProviders.ToArray(); - + _serviceProvider = serviceProvider; _cache = new ConcurrentDictionary(); + + var loggerFactory = serviceProvider.GetRequiredService(); + var logger = loggerFactory.CreateLogger(); + logger.RegisteredModelBinderProviders(_providers); } /// @@ -195,6 +220,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return _cache.TryGetValue(new Key(metadata, cacheToken), out binder); } + private static IServiceProvider GetDefaultServices() + { + var services = new ServiceCollection(); + services.AddSingleton(NullLoggerFactory.Instance); + return services.BuildServiceProvider(); + } + private class DefaultModelBinderProviderContext : ModelBinderProviderContext { private readonly ModelBinderFactory _factory; @@ -245,6 +277,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public Dictionary Visited { get; } + public override IServiceProvider Services => _factory._serviceProvider; + public override IModelBinder CreateBinder(ModelMetadata metadata) { if (metadata == null) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs index f751be5f96..647fc86e45 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs @@ -6,6 +6,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding { @@ -20,17 +22,47 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding private readonly IModelValidatorProvider _validatorProvider; private readonly ValidatorCache _validatorCache; + /// + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an . + /// Initializes a new instance of . + /// + /// The . + /// The . + /// The . + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that also takes an " + nameof(ILoggerFactory) + ".")] + public ParameterBinder( + IModelMetadataProvider modelMetadataProvider, + IModelBinderFactory modelBinderFactory, + IModelValidatorProvider validatorProvider) + : this( + modelMetadataProvider, + modelBinderFactory, + validatorProvider, + validatorForBackCompatOnly: null, + loggerFactory: NullLoggerFactory.Instance) + { + } + /// /// Initializes a new instance of . /// /// The . /// The . /// The . + /// The . public ParameterBinder( IModelMetadataProvider modelMetadataProvider, IModelBinderFactory modelBinderFactory, - IModelValidatorProvider validatorProvider) - : this(modelMetadataProvider, modelBinderFactory, validatorProvider, null) + IModelValidatorProvider validatorProvider, + ILoggerFactory loggerFactory) + : this( + modelMetadataProvider, + modelBinderFactory, + validatorProvider, + validatorForBackCompatOnly: null, + loggerFactory: loggerFactory) { if (validatorProvider == null) { @@ -39,17 +71,27 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } /// - /// Initializes a new instance of . + /// This constructor is obsolete and will be removed in a future version. The recommended alternative + /// is the overload that also takes an and + /// instead of an . + /// Initializes a new instance of . /// /// The . /// The . /// The . - [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative is the overload that takes a " + nameof(IModelValidatorProvider) + " instead of a " + nameof(IObjectModelValidator) + ".")] + [Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative" + + " is the overload that takes an " + nameof(IModelValidatorProvider) + " and " + nameof(ILoggerFactory) + + " instead of an " + nameof(IObjectModelValidator) + ".")] public ParameterBinder( IModelMetadataProvider modelMetadataProvider, IModelBinderFactory modelBinderFactory, IObjectModelValidator validator) - : this(modelMetadataProvider, modelBinderFactory, null, validator) + : this( + modelMetadataProvider, + modelBinderFactory, + validatorProvider: null, + validatorForBackCompatOnly: validator, + loggerFactory: NullLoggerFactory.Instance) { // Note: When this obsolete constructor overload is removed, also remember // to remove the validatorForBackCompatOnly field. @@ -64,7 +106,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding IModelMetadataProvider modelMetadataProvider, IModelBinderFactory modelBinderFactory, IModelValidatorProvider validatorProvider, - IObjectModelValidator validatorForBackCompatOnly) + IObjectModelValidator validatorForBackCompatOnly, + ILoggerFactory loggerFactory) { if (modelMetadataProvider == null) { @@ -76,13 +119,24 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding throw new ArgumentNullException(nameof(modelBinderFactory)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _modelMetadataProvider = modelMetadataProvider; _modelBinderFactory = modelBinderFactory; _validatorProvider = validatorProvider; _validatorForBackCompatOnly = validatorForBackCompatOnly; _validatorCache = new ValidatorCache(); + Logger = loggerFactory.CreateLogger(GetType()); } + /// + /// The used for logging in this binder. + /// + protected ILogger Logger { get; } + /// /// Initializes and binds a model specified by . /// @@ -200,6 +254,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding parameter.Name); modelBindingContext.Model = value; + Logger.AttemptingToBindParameterOrProperty(parameter, modelBindingContext); + var parameterModelName = parameter.BindingInfo?.BinderModelName ?? metadata.BinderModelName; if (parameterModelName != null) { @@ -219,6 +275,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding await modelBinder.BindModelAsync(modelBindingContext); + Logger.DoneAttemptingToBindParameterOrProperty(parameter, modelBindingContext); + var modelBindingResult = modelBindingContext.Result; if (_validatorForBackCompatOnly != null) @@ -237,11 +295,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } else { + Logger.AttemptingToValidateParameterOrProperty(parameter, modelBindingContext); + EnforceBindRequiredAndValidate( actionContext, metadata, modelBindingContext, modelBindingResult); + + Logger.DoneAttemptingToValidateParameterOrProperty(parameter, modelBindingContext); } return modelBindingResult; diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs index 1c9def2ffc..4ff9dac6ec 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs @@ -18,6 +18,9 @@ using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Mvc.TestCommon; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; using Moq; @@ -2832,7 +2835,13 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test private static ControllerBase GetController(IModelBinder binder, IValueProvider valueProvider) { var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); - var httpContext = new DefaultHttpContext(); + var services = new ServiceCollection(); + services.AddSingleton(NullLoggerFactory.Instance); + + var httpContext = new DefaultHttpContext() + { + RequestServices = services.BuildServiceProvider() + }; var validatorProviders = new[] { diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerActionInvokerCacheTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerActionInvokerCacheTest.cs index 1ee7212840..c96254795e 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerActionInvokerCacheTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerActionInvokerCacheTest.cs @@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -108,7 +109,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal new ParameterBinder( modelMetadataProvider, modelBinderFactory, - Mock.Of()), + Mock.Of(), + NullLoggerFactory.Instance), modelBinderFactory, modelMetadataProvider, filterProviders, diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerBinderDelegateProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerBinderDelegateProviderTest.cs index dd4a039c6e..e0595ef42c 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerBinderDelegateProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerBinderDelegateProviderTest.cs @@ -17,6 +17,9 @@ using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -1032,10 +1035,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal return Task.FromResult(result); }); - var controllerContext = new ControllerContext - { - ActionDescriptor = actionDescriptor, - }; + var controllerContext = GetControllerContext(actionDescriptor); var arguments = new Dictionary(StringComparer.Ordinal); var modelState = controllerContext.ModelState; @@ -1063,10 +1063,16 @@ namespace Microsoft.AspNetCore.Mvc.Internal private static ControllerContext GetControllerContext(ControllerActionDescriptor descriptor = null) { + var services = new ServiceCollection(); + services.AddSingleton(NullLoggerFactory.Instance); + var context = new ControllerContext() { ActionDescriptor = descriptor ?? GetActionDescriptor(), - HttpContext = new DefaultHttpContext(), + HttpContext = new DefaultHttpContext() + { + RequestServices = services.BuildServiceProvider() + }, RouteData = new RouteData(), }; @@ -1140,7 +1146,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal return new ParameterBinder( modelMetadataProvider ?? TestModelMetadataProvider.CreateDefaultProvider(), factory, - validatorProvider.Object); + validatorProvider.Object, + NullLoggerFactory.Instance); } private static Mock CreateMockValidator() diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/MiddlewareFilterTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/MiddlewareFilterTest.cs index 2767f6c054..f4fac6c6dd 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/MiddlewareFilterTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/MiddlewareFilterTest.cs @@ -448,7 +448,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal : base( new EmptyModelMetadataProvider(), TestModelBinderFactory.CreateDefault(), - Mock.Of()) + Mock.Of(), + NullLoggerFactory.Instance) { _actionParameters = actionParameters; } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderTest.cs index 1c41efa5ad..8c3a372f06 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ModelBinding.Internal; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders @@ -27,7 +28,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders typeof(ModelWithIntArrayProperty), nameof(ModelWithIntArrayProperty.ArrayProperty)); - var binder = new ArrayModelBinder(new SimpleTypeModelBinder(typeof(int))); + var binder = new ArrayModelBinder( + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -43,7 +46,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task ArrayModelBinder_CreatesEmptyCollection_IfIsTopLevelObject() { // Arrange - var binder = new ArrayModelBinder(new SimpleTypeModelBinder(typeof(string))); + var binder = new ArrayModelBinder( + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.IsTopLevelObject = true; @@ -70,7 +75,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task ArrayModelBinder_DoesNotCreateCollection_IfNotIsTopLevelObject(string prefix) { // Arrange - var binder = new ArrayModelBinder(new SimpleTypeModelBinder(typeof(string))); + var binder = new ArrayModelBinder( + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.ModelName = ModelNames.CreatePropertyModelName(prefix, "ArrayProperty"); @@ -126,7 +133,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders typeof(ModelWithIntArrayProperty), nameof(ModelWithIntArrayProperty.ArrayProperty)); - var binder = new ArrayModelBinder(new SimpleTypeModelBinder(typeof(int))); + var binder = new ArrayModelBinder( + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/BodyModelBinderTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/BodyModelBinderTests.cs index 2babd023db..5cc7342bb3 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/BodyModelBinderTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/BodyModelBinderTests.cs @@ -648,8 +648,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders await binder.BindModelAsync(bindingContext); // Assert - Assert.Equal($"Rejected input formatter '{typeof(TestInputFormatter)}' for content type 'application/json'.", sink.Writes[0].State.ToString()); - Assert.Equal($"Selected input formatter '{typeof(TestInputFormatter)}' for content type 'application/json'.", sink.Writes[1].State.ToString()); + Assert.Equal($"Attempting to bind model of type '{typeof(Person)}' using the name 'someName' in request data ...", sink.Writes[0].State.ToString()); + Assert.Equal($"Rejected input formatter '{typeof(TestInputFormatter)}' for content type 'application/json'.", sink.Writes[1].State.ToString()); + Assert.Equal($"Selected input formatter '{typeof(TestInputFormatter)}' for content type 'application/json'.", sink.Writes[2].State.ToString()); } [Fact] @@ -677,6 +678,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Assert Assert.Collection( sink.Writes, + write => Assert.Equal( + $"Attempting to bind model of type '{typeof(Person)}' using the name 'someName' in request data ...", write.State.ToString()), write => Assert.Equal( $"Rejected input formatter '{typeof(TestInputFormatter)}' for content type 'multipart/form-data'.", write.State.ToString()), write => Assert.Equal( @@ -684,7 +687,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders write => Assert.Equal( "No input formatter was found to support the content type 'multipart/form-data' for use with the [FromBody] attribute.", write.State.ToString()), write => Assert.Equal( - $"To use model binding, remove the [FromBody] attribute from the property or parameter named '{bindingContext.ModelName}' with model type '{bindingContext.ModelType}'.", write.State.ToString())); + $"To use model binding, remove the [FromBody] attribute from the property or parameter named '{bindingContext.ModelName}' with model type '{bindingContext.ModelType}'.", write.State.ToString()), + write => Assert.Equal( + $"Done attempting to bind model of type '{typeof(Person)}' using the name 'someName'.", write.State.ToString())); } [Fact] diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ByteArrayModelBinderTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ByteArrayModelBinderTests.cs index fa43421765..4679658416 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ByteArrayModelBinderTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ByteArrayModelBinderTests.cs @@ -3,6 +3,7 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders @@ -21,7 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders }; var bindingContext = GetBindingContext(valueProvider, typeof(byte[])); - var binder = new ByteArrayModelBinder(); + var binder = new ByteArrayModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -45,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders }; var bindingContext = GetBindingContext(valueProvider, typeof(byte[])); - var binder = new ByteArrayModelBinder(); + var binder = new ByteArrayModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -68,7 +69,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders }; var bindingContext = GetBindingContext(valueProvider, typeof(byte[])); - var binder = new ByteArrayModelBinder(); + var binder = new ByteArrayModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -90,7 +91,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders }; var bindingContext = GetBindingContext(valueProvider, typeof(byte[])); - var binder = new ByteArrayModelBinder(); + var binder = new ByteArrayModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/CollectionModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/CollectionModelBinderTest.cs index b11ebf38d3..b34cd09da5 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/CollectionModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/CollectionModelBinderTest.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders @@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "someName[baz]", "200" } }; var bindingContext = GetModelBindingContext(valueProvider); - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); // Act var collectionResult = await binder.BindComplexCollectionFromIndexes( @@ -52,7 +53,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "someName[3]", "400" } }; var bindingContext = GetModelBindingContext(valueProvider); - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); // Act var boundCollection = await binder.BindComplexCollectionFromIndexes(bindingContext, indexNames: null); @@ -79,7 +80,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders }; var bindingContext = GetModelBindingContext(valueProvider, isReadOnly); var modelState = bindingContext.ModelState; - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -110,7 +111,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var modelState = bindingContext.ModelState; var list = new List(); bindingContext.Model = list; - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -136,7 +137,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders }; var bindingContext = GetModelBindingContext(valueProvider, isReadOnly); var modelState = bindingContext.ModelState; - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -162,7 +163,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var modelState = bindingContext.ModelState; var list = new List(); bindingContext.Model = list; - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -178,7 +179,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task BindModelAsync_SimpleCollectionWithNullValue_Succeeds() { // Arrange - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); var valueProvider = new SimpleValueProvider { { "someName", null }, @@ -199,7 +200,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task BindSimpleCollection_RawValueIsEmptyCollection_ReturnsEmptyList() { // Arrange - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); var context = GetModelBindingContext(new SimpleValueProvider()); // Act @@ -214,7 +215,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task CollectionModelBinder_CreatesEmptyCollection_IfIsTopLevelObject() { // Arrange - var binder = new CollectionModelBinder(new StubModelBinder(result: ModelBindingResult.Failed())); + var binder = new CollectionModelBinder( + new StubModelBinder(result: ModelBindingResult.Failed()), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.IsTopLevelObject = true; @@ -241,7 +244,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task CollectionModelBinder_DoesNotCreateEmptyCollection_IfModelNonNull() { // Arrange - var binder = new CollectionModelBinder(new StubModelBinder(result: ModelBindingResult.Failed())); + var binder = new CollectionModelBinder( + new StubModelBinder(result: ModelBindingResult.Failed()), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.IsTopLevelObject = true; @@ -272,7 +277,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task CollectionModelBinder_DoesNotCreateCollection_IfNotIsTopLevelObject(string prefix) { // Arrange - var binder = new CollectionModelBinder(new StubModelBinder(result: ModelBindingResult.Failed())); + var binder = new CollectionModelBinder( + new StubModelBinder(result: ModelBindingResult.Failed()), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.ModelName = ModelNames.CreatePropertyModelName(prefix, "ListProperty"); @@ -313,7 +320,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public void CanCreateInstance_ReturnsExpectedValue(Type modelType, bool expectedResult) { // Arrange - var binder = new CollectionModelBinder(CreateIntBinder()); + var binder = new CollectionModelBinder(CreateIntBinder(), NullLoggerFactory.Instance); // Act var result = binder.CanCreateInstance(modelType); @@ -335,7 +342,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders mbc.Result = ModelBindingResult.Success(42); }); - var modelBinder = new CollectionModelBinder(elementBinder); + var modelBinder = new CollectionModelBinder(elementBinder, NullLoggerFactory.Instance); // Act var boundCollection = await modelBinder.BindSimpleCollection( diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ComplexTypeModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ComplexTypeModelBinderTest.cs index c820c31476..cc9caed07e 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ComplexTypeModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ComplexTypeModelBinderTest.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -1352,7 +1353,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } public TestableComplexTypeModelBinder(IDictionary propertyBinders) - : base(propertyBinders) + : base(propertyBinders, NullLoggerFactory.Instance) { Results = new Dictionary(); } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DecimalModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DecimalModelBinderTest.cs index ad0ba31f59..21ec379c4a 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DecimalModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DecimalModelBinderTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Globalization; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders protected override IModelBinder GetBinder(NumberStyles numberStyles) { - return new DecimalModelBinder(numberStyles); + return new DecimalModelBinder(numberStyles, NullLoggerFactory.Instance); } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs index 3c0ce5563e..c155ed8b03 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Primitives; using Xunit; @@ -36,8 +37,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.ValueProvider = CreateEnumerableValueProvider("{0}", values); var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(int)), - new SimpleTypeModelBinder(typeof(string))); + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -76,8 +78,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.Model = dictionary; var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(int)), - new SimpleTypeModelBinder(typeof(string))); + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -132,8 +135,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // Arrange var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(string)), - new SimpleTypeModelBinder(typeof(string))); + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.ModelName = modelName; @@ -168,8 +172,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders }; var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(string)), - new SimpleTypeModelBinder(typeof(string))); + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.ModelName = "prefix"; @@ -218,8 +223,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var stringDictionary = dictionary.ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value.ToString()); var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(long)), - new SimpleTypeModelBinder(typeof(int))); + new SimpleTypeModelBinder(typeof(long), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.ModelName = "prefix"; @@ -271,12 +277,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var valueMetadata = metadataProvider.GetMetadataForType(typeof(ModelWithProperties)); var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(int)), + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), new ComplexTypeModelBinder(new Dictionary() { - { valueMetadata.Properties["Id"], new SimpleTypeModelBinder(typeof(int)) }, - { valueMetadata.Properties["Name"], new SimpleTypeModelBinder(typeof(string)) }, - })); + { valueMetadata.Properties["Id"], new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance) }, + { valueMetadata.Properties["Name"], new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance) }, + }, + NullLoggerFactory.Instance), + NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -310,8 +318,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Arrange var expectedDictionary = new SortedDictionary(dictionary); var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(string)), - new SimpleTypeModelBinder(typeof(string))); + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.ModelName = modelName; @@ -339,8 +348,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // Arrange var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(string)), - new SimpleTypeModelBinder(typeof(string))); + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.IsTopLevelObject = true; @@ -368,8 +378,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // Arrange var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(int)), - new SimpleTypeModelBinder(typeof(int))); + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.ModelName = ModelNames.CreatePropertyModelName(prefix, "ListProperty"); @@ -412,8 +423,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // Arrange var binder = new DictionaryModelBinder( - new SimpleTypeModelBinder(typeof(int)), - new SimpleTypeModelBinder(typeof(int))); + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); // Act var result = binder.CanCreateInstance(modelType); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DoubleModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DoubleModelBinderTest.cs index e0d28c3836..4d028ff8b4 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DoubleModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DoubleModelBinderTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Globalization; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders protected override IModelBinder GetBinder(NumberStyles numberStyles) { - return new DoubleModelBinder(numberStyles); + return new DoubleModelBinder(numberStyles, NullLoggerFactory.Instance); } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FloatModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FloatModelBinderTest.cs index d0a7a16fc8..2679473092 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FloatModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FloatModelBinderTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Globalization; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders protected override IModelBinder GetBinder(NumberStyles numberStyles) { - return new FloatModelBinder(numberStyles); + return new FloatModelBinder(numberStyles, NullLoggerFactory.Instance); } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormCollectionModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormCollectionModelBinderTest.cs index 7b5ae13a1c..ad8eca9bc3 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormCollectionModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormCollectionModelBinderTest.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Primitives; using Moq; using Xunit; @@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders }); var httpContext = GetMockHttpContext(formCollection); var bindingContext = GetBindingContext(typeof(IFormCollection), httpContext); - var binder = new FormCollectionModelBinder(); + var binder = new FormCollectionModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -47,7 +48,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Arrange var httpContext = GetMockHttpContext(null, hasForm: false); var bindingContext = GetBindingContext(typeof(IFormCollection), httpContext); - var binder = new FormCollectionModelBinder(); + var binder = new FormCollectionModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormFileModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormFileModelBinderTest.cs index ac15b3fe2a..d738cdc6ff 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormFileModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormFileModelBinderTest.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -23,7 +24,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders formFiles.Add(GetMockFormFile("file", "file1.txt")); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(typeof(IEnumerable), httpContext); - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -44,7 +45,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var formFiles = GetTwoFiles(); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(typeof(IEnumerable), httpContext); - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -73,7 +74,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task FormFileModelBinder_BindsFiles_ForCollectionsItCanCreate(Type destinationType) { // Arrange - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); var formFiles = GetTwoFiles(); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(destinationType, httpContext); @@ -94,7 +95,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var formFiles = GetTwoFiles(); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(typeof(IFormFile), httpContext); - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -112,7 +113,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var formFiles = new FormFileCollection(); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(typeof(IFormFile), httpContext); - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -130,7 +131,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders formFiles.Add(GetMockFormFile("different name", "file1.txt")); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(typeof(IFormFile), httpContext); - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -156,7 +157,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.FieldName = "FieldName"; bindingContext.ModelName = "ModelName"; - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -176,7 +177,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders formFiles.Add(new Mock().Object); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(typeof(IFormFile), httpContext); - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -194,7 +195,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders formFiles.Add(GetMockFormFile("file", "")); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(typeof(IFormFile), httpContext); - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -208,7 +209,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task FormFileModelBinder_ReturnsResult_ForReadOnlyDestination() { // Arrange - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); var formFiles = GetTwoFiles(); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContextForReadOnlyArray(httpContext); @@ -225,7 +226,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task FormFileModelBinder_ReturnsFailedResult_ForCollectionsItCannotCreate() { // Arrange - var binder = new FormFileModelBinder(); + var binder = new FormFileModelBinder(NullLoggerFactory.Instance); var formFiles = GetTwoFiles(); var httpContext = GetMockHttpContext(GetMockFormCollection(formFiles)); var bindingContext = GetBindingContext(typeof(ISet), httpContext); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderTests.cs index f04680cc19..dcc751d20a 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderTests.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders @@ -21,7 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders public async Task BindModelAsync_ReturnsNonEmptyResult_ForAllTypes_WithHeaderBindingSource(Type type) { // Arrange - var binder = new HeaderModelBinder(); + var binder = new HeaderModelBinder(NullLoggerFactory.Instance); var bindingContext = GetBindingContext(type); // Act @@ -38,7 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var type = typeof(string[]); var header = "Accept"; var headerValue = "application/json,text/json"; - var binder = new HeaderModelBinder(); + var binder = new HeaderModelBinder(NullLoggerFactory.Instance); var bindingContext = GetBindingContext(type); bindingContext.FieldName = header; @@ -59,7 +60,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var type = typeof(string); var header = "User-Agent"; var headerValue = "UnitTest"; - var binder = new HeaderModelBinder(); + var binder = new HeaderModelBinder(NullLoggerFactory.Instance); var bindingContext = GetBindingContext(type); bindingContext.FieldName = header; @@ -85,7 +86,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Arrange var header = "Accept"; var headerValue = "application/json,text/json"; - var binder = new HeaderModelBinder(); + var binder = new HeaderModelBinder(NullLoggerFactory.Instance); var bindingContext = GetBindingContext(destinationType); bindingContext.FieldName = header; @@ -106,7 +107,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Arrange var header = "Accept"; var headerValue = "application/json,text/json"; - var binder = new HeaderModelBinder(); + var binder = new HeaderModelBinder(NullLoggerFactory.Instance); var bindingContext = GetBindingContextForReadOnlyArray(); bindingContext.FieldName = header; @@ -126,7 +127,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Arrange var header = "Accept"; var headerValue = "application/json,text/json"; - var binder = new HeaderModelBinder(); + var binder = new HeaderModelBinder(NullLoggerFactory.Instance); var bindingContext = GetBindingContext(typeof(ISet)); bindingContext.FieldName = header; diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/KeyValuePairModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/KeyValuePairModelBinderTest.cs index 3436568fbf..55fa61e919 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/KeyValuePairModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/KeyValuePairModelBinderTest.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders @@ -19,7 +20,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Create string binder to create the value but not the key. var bindingContext = GetBindingContext(valueProvider, typeof(KeyValuePair)); - var binder = new KeyValuePairModelBinder(CreateIntBinder(false), CreateStringBinder()); + var binder = new KeyValuePairModelBinder( + CreateIntBinder(false), + CreateStringBinder(), + NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -41,8 +45,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Create int binder to create the value but not the key. var bindingContext = GetBindingContext(valueProvider, typeof(KeyValuePair)); - var binder = new KeyValuePairModelBinder(CreateIntBinder(), CreateStringBinder(false)); - + var binder = new KeyValuePairModelBinder( + CreateIntBinder(), + CreateStringBinder(false), + NullLoggerFactory.Instance); + // Act await binder.BindModelAsync(bindingContext); @@ -64,7 +71,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Create int binder to create the value but not the key. var bindingContext = GetBindingContext(valueProvider, typeof(KeyValuePair)); - var binder = new KeyValuePairModelBinder(CreateIntBinder(false), CreateStringBinder(false)); + var binder = new KeyValuePairModelBinder( + CreateIntBinder(false), + CreateStringBinder(false), + NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -82,7 +92,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var valueProvider = new SimpleValueProvider(); var bindingContext = GetBindingContext(valueProvider, typeof(KeyValuePair)); - var binder = new KeyValuePairModelBinder(CreateIntBinder(), CreateStringBinder()); + var binder = new KeyValuePairModelBinder( + CreateIntBinder(), + CreateStringBinder(), + NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -120,7 +133,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var valueProvider = new SimpleValueProvider(); var bindingContext = GetBindingContext(valueProvider, typeof(KeyValuePair)); - var binder = new KeyValuePairModelBinder(innerBinder, innerBinder); + var binder = new KeyValuePairModelBinder(innerBinder, innerBinder, NullLoggerFactory.Instance); // Act var result = await binder.TryBindStrongModel(bindingContext, innerBinder, "Key", "someName.Key"); @@ -135,8 +148,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // Arrange var binder = new KeyValuePairModelBinder( - new SimpleTypeModelBinder(typeof(string)), - new SimpleTypeModelBinder(typeof(string))); + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.IsTopLevelObject = true; @@ -165,8 +179,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // Arrange var binder = new KeyValuePairModelBinder( - new SimpleTypeModelBinder(typeof(string)), - new SimpleTypeModelBinder(typeof(string))); + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), + NullLoggerFactory.Instance); var bindingContext = CreateContext(); bindingContext.ModelName = ModelNames.CreatePropertyModelName(prefix, "KeyValuePairProperty"); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/SimpleTypeModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/SimpleTypeModelBinderTest.cs index e46c61aa41..4831151d13 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/SimpleTypeModelBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/SimpleTypeModelBinderTest.cs @@ -5,6 +5,7 @@ using System; using System.Globalization; using System.Threading.Tasks; using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders @@ -25,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", value } }; - var binder = new SimpleTypeModelBinder(typeof(string)); + var binder = new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -53,7 +54,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders .DisplayDetails(d => d.ConvertEmptyStringToNull = false); bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(typeof(string)); - var binder = new SimpleTypeModelBinder(typeof(string)); + var binder = new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -99,7 +100,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", "some-value" } }; - var binder = new SimpleTypeModelBinder(destinationType); + var binder = new SimpleTypeModelBinder(destinationType, NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -118,7 +119,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { { "theModelName", string.Empty } }; - var binder = new SimpleTypeModelBinder(destinationType); + var binder = new SimpleTypeModelBinder(destinationType, NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -143,7 +144,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", "not an integer" } }; - var binder = new SimpleTypeModelBinder(typeof(int)); + var binder = new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -161,7 +162,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // Arrange var bindingContext = GetBindingContext(typeof(int)); - var binder = new SimpleTypeModelBinder(typeof(int)); + var binder = new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -183,7 +184,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", value } }; - var binder = new SimpleTypeModelBinder(typeof(string)); + var binder = new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -203,7 +204,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", "12" } }; - var binder = new SimpleTypeModelBinder(typeof(int?)); + var binder = new SimpleTypeModelBinder(typeof(int?), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -224,7 +225,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", "12.5" } }; - var binder = new SimpleTypeModelBinder(typeof(double?)); + var binder = new SimpleTypeModelBinder(typeof(double?), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -245,7 +246,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", "42" } }; - var binder = new SimpleTypeModelBinder(typeof(int)); + var binder = new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -287,7 +288,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", "32,000" } }; - var binder = new SimpleTypeModelBinder(type); + var binder = new SimpleTypeModelBinder(type, NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -315,7 +316,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", "12,5" } }; - var binder = new SimpleTypeModelBinder(typeof(decimal)); + var binder = new SimpleTypeModelBinder(typeof(decimal), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -336,7 +337,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", "12,5" } }; - var binder = new SimpleTypeModelBinder(typeof(decimal)); + var binder = new SimpleTypeModelBinder(typeof(decimal), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -360,7 +361,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", new object[] { "Value1" } } }; - var binder = new SimpleTypeModelBinder(typeof(IntEnum)); + var binder = new SimpleTypeModelBinder(typeof(IntEnum), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -381,7 +382,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", new object[] { "1" } } }; - var binder = new SimpleTypeModelBinder(typeof(IntEnum)); + var binder = new SimpleTypeModelBinder(typeof(IntEnum), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -422,7 +423,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", flagsEnumValue } }; - var binder = new SimpleTypeModelBinder(typeof(IntEnum)); + var binder = new SimpleTypeModelBinder(typeof(IntEnum), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); @@ -445,7 +446,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { "theModelName", flagsEnumValue } }; - var binder = new SimpleTypeModelBinder(typeof(FlagsEnum)); + var binder = new SimpleTypeModelBinder(typeof(FlagsEnum), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/DefaultModelBindingContextTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/DefaultModelBindingContextTest.cs index f955897f99..642082eb67 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/DefaultModelBindingContextTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/DefaultModelBindingContextTest.cs @@ -9,6 +9,9 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Primitives; using Xunit; @@ -73,7 +76,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding // Act var context = DefaultModelBindingContext.CreateBindingContext( - new ActionContext(), + GetActionContext(), original, metadataProvider.GetMetadataForType(typeof(object)), new BindingInfo() { BindingSource = BindingSource.Query }, @@ -96,7 +99,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var original = CreateDefaultValueProvider(); var context = DefaultModelBindingContext.CreateBindingContext( - new ActionContext(), + GetActionContext(), original, metadataProvider.GetMetadataForType(typeof(string)), new BindingInfo(), @@ -125,7 +128,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var original = CreateDefaultValueProvider(); var context = DefaultModelBindingContext.CreateBindingContext( - new ActionContext(), + GetActionContext(), original, metadataProvider.GetMetadataForType(typeof(string)), new BindingInfo() { BindingSource = BindingSource.Query }, @@ -155,6 +158,20 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding Assert.Equal(typeof(int), bindingContext.ModelType); } + private static ActionContext GetActionContext() + { + var services = new ServiceCollection(); + services.AddSingleton(NullLoggerFactory.Instance); + + return new ActionContext() + { + HttpContext = new DefaultHttpContext() + { + RequestServices = services.BuildServiceProvider() + } + }; + } + private static CompositeValueProvider CreateDefaultValueProvider() { var result = new CompositeValueProvider(); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBinderFactoryTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBinderFactoryTest.cs index 4cacf76853..58a2d9a841 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBinderFactoryTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBinderFactoryTest.cs @@ -5,6 +5,9 @@ using System; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -21,7 +24,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding $"empty. At least one '{typeof(IModelBinderProvider).FullName}' is required to model bind."; var metadataProvider = new TestModelMetadataProvider(); var options = Options.Create(new MvcOptions()); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { Metadata = metadataProvider.GetMetadataForType(typeof(string)), @@ -40,7 +46,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var options = Options.Create(new MvcOptions()); options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(_ => null)); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { Metadata = metadataProvider.GetMetadataForType(typeof(string)), @@ -72,7 +81,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return null; })); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -95,7 +107,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding .ForProperty(nameof(Widget.Id)) .BindingDetails(m => m.IsBindingAllowed = false); - var modelBinder = new ByteArrayModelBinder(); + var modelBinder = new ByteArrayModelBinder(NullLoggerFactory.Instance); var options = Options.Create(new MvcOptions()); options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(c => @@ -108,7 +120,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return null; })); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -145,7 +160,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return null; })); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -182,7 +200,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return Mock.Of(); })); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -209,7 +230,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return Mock.Of(); })); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -237,7 +261,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return Mock.Of(); })); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -345,7 +372,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var options = Options.Create(new MvcOptions()); options.Value.ModelBinderProviders.Insert(0, modelBinderProvider); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var factoryContext = new ModelBinderFactoryContext { BindingInfo = parameterBindingInfo, @@ -398,7 +428,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding options.Value.ModelBinderProviders.Add(widgetProvider); options.Value.ModelBinderProviders.Add(widgetIdProvider); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -457,7 +490,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding options.Value.ModelBinderProviders.Add(widgetProvider); options.Value.ModelBinderProviders.Add(widgetIdProvider); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -508,7 +544,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding options.Value.ModelBinderProviders.Add(widgetProvider); options.Value.ModelBinderProviders.Add(widgetIdProvider); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -569,7 +608,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding options.Value.ModelBinderProviders.Add(widgetProvider); options.Value.ModelBinderProviders.Add(widgetIdProvider); - var factory = new ModelBinderFactory(metadataProvider, options); + var factory = new ModelBinderFactory( + metadataProvider, + options, + GetServices()); var context = new ModelBinderFactoryContext() { @@ -597,6 +639,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding Assert.Equal(0, widgetIdProvider.SuccessCount); } + private IServiceProvider GetServices() + { + var services = new ServiceCollection(); + services.AddSingleton(NullLoggerFactory.Instance); + return services.BuildServiceProvider(); + } + private class Widget { public WidgetId Id { get; set; } diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBindingHelperTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBindingHelperTest.cs index 41ac49cdf8..062b5fddce 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBindingHelperTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBindingHelperTest.cs @@ -16,6 +16,9 @@ using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; using Microsoft.AspNetCore.Mvc.ModelBinding.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -36,7 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var result = await ModelBindingHelper.TryUpdateModelAsync( model, string.Empty, - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binder), Mock.Of(), @@ -70,7 +73,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var valueProvider = new TestValueProvider(values); var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); - var actionContext = new ActionContext() { HttpContext = new DefaultHttpContext() }; + var actionContext = GetActionContext(); var modelState = actionContext.ModelState; // Act @@ -117,7 +120,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var result = await ModelBindingHelper.TryUpdateModelAsync( model, "", - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binderProviders), valueProvider, @@ -141,7 +144,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var result = await ModelBindingHelper.TryUpdateModelAsync( model, string.Empty, - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binder), Mock.Of(), @@ -195,7 +198,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var result = await ModelBindingHelper.TryUpdateModelAsync( model, "", - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binderProviders), valueProvider, @@ -221,7 +224,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var result = await ModelBindingHelper.TryUpdateModelAsync( model, string.Empty, - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binder), Mock.Of(), @@ -271,7 +274,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var result = await ModelBindingHelper.TryUpdateModelAsync( model, "", - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), TestModelMetadataProvider.CreateDefaultProvider(), GetModelBinderFactory(binderProviders), valueProvider, @@ -322,7 +325,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var result = await ModelBindingHelper.TryUpdateModelAsync( model, "", - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binderProviders), valueProvider, @@ -469,7 +472,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding model, model.GetType(), prefix: "", - actionContext: new ActionContext() { HttpContext = new DefaultHttpContext() }, + actionContext: GetActionContext(), metadataProvider: metadataProvider, modelBinderFactory: GetModelBinderFactory(binder), valueProvider: Mock.Of(), @@ -524,7 +527,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding model, model.GetType(), "", - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binderProviders), valueProvider, @@ -552,7 +555,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding model, modelType: model.GetType(), prefix: "", - actionContext: new ActionContext() { HttpContext = new DefaultHttpContext() }, + actionContext: GetActionContext(), metadataProvider: metadataProvider, modelBinderFactory: GetModelBinderFactory(binder.Object), valueProvider: Mock.Of(), @@ -592,7 +595,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding model, model.GetType(), "", - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binderProviders), valueProvider, @@ -623,7 +626,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding model, typeof(User), "", - new ActionContext() { HttpContext = new DefaultHttpContext() }, + GetActionContext(), metadataProvider, GetModelBinderFactory(binder.Object), Mock.Of(), @@ -1492,6 +1495,20 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding Assert.False(result); } + private static ActionContext GetActionContext() + { + var services = new ServiceCollection(); + services.AddSingleton(NullLoggerFactory.Instance); + + return new ActionContext() + { + HttpContext = new DefaultHttpContext() + { + RequestServices = services.BuildServiceProvider() + } + }; + } + private static DefaultModelBindingContext GetBindingContextForProperty(string propertyName) { var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ParameterBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ParameterBinderTest.cs index 902187908b..222075de82 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ParameterBinderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ParameterBinderTest.cs @@ -5,12 +5,16 @@ using System; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.DataAnnotations; using Microsoft.AspNetCore.Mvc.DataAnnotations.Internal; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -94,9 +98,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var parameterBinder = new ParameterBinder( metadataProvider, factory.Object, - CreateMockValidatorProvider()); + CreateMockValidatorProvider(), + NullLoggerFactory.Instance); - var controllerContext = new ControllerContext(); + var controllerContext = GetControllerContext(); // Act & Assert await parameterBinder.BindModelAsync(controllerContext, new SimpleValueProvider(), parameterDescriptor); @@ -144,7 +149,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var argumentBinder = new ParameterBinder( metadataProvider, factory.Object, - CreateMockValidatorProvider()); + CreateMockValidatorProvider(), + NullLoggerFactory.Instance); var valueProvider = new SimpleValueProvider { @@ -152,7 +158,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding }; var valueProviderFactory = new SimpleValueProviderFactory(valueProvider); - var controllerContext = new ControllerContext(); + var controllerContext = GetControllerContext(); // Act & Assert await argumentBinder.BindModelAsync(controllerContext, valueProvider, parameterDescriptor); @@ -163,7 +169,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public async Task BindModelAsync_EnforcesTopLevelBindRequired() { // Arrange - var actionContext = new ControllerContext(); + var actionContext = GetControllerContext(); var mockModelMetadata = CreateMockModelMetadata(); mockModelMetadata.Setup(o => o.IsBindingRequired).Returns(true); @@ -193,7 +199,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public async Task BindModelAsync_EnforcesTopLevelRequired() { // Arrange - var actionContext = new ControllerContext(); + var actionContext = GetControllerContext(); var mockModelMetadata = CreateMockModelMetadata(); mockModelMetadata.Setup(o => o.IsRequired).Returns(true); mockModelMetadata.Setup(o => o.DisplayName).Returns("My Display Name"); @@ -233,7 +239,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public async Task BindModelAsync_EnforcesTopLevelDataAnnotationsAttribute() { // Arrange - var actionContext = new ControllerContext(); + var actionContext = GetControllerContext(); var mockModelMetadata = CreateMockModelMetadata(); var validationAttribute = new RangeAttribute(1, 100); mockModelMetadata.Setup(o => o.DisplayName).Returns("My Display Name"); @@ -272,7 +278,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public async Task BindModelAsync_SupportsIObjectModelValidatorForBackCompat() { // Arrange - var actionContext = new ControllerContext(); + var actionContext = GetControllerContext(); var mockValidator = new Mock(MockBehavior.Strict); mockValidator @@ -309,6 +315,20 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding actionContext.ModelState.Single().Value.Errors.Single().ErrorMessage); } + private static ControllerContext GetControllerContext() + { + var services = new ServiceCollection(); + services.AddSingleton(NullLoggerFactory.Instance); + + return new ControllerContext() + { + HttpContext = new DefaultHttpContext() + { + RequestServices = services.BuildServiceProvider() + } + }; + } + private static Mock CreateMockModelMetadata() { var mockModelMetadata = new Mock(); @@ -344,7 +364,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return new ParameterBinder( mockModelMetadataProvider.Object, mockModelBinderFactory.Object, - CreateMockValidatorProvider(validator)); + CreateMockValidatorProvider(validator), + NullLoggerFactory.Instance); } private static ParameterBinder CreateBackCompatParameterBinder( diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/TestModelBinderProviderContext.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/TestModelBinderProviderContext.cs index d8b963e798..707c277d10 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/TestModelBinderProviderContext.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/TestModelBinderProviderContext.cs @@ -3,6 +3,9 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.AspNetCore.Mvc.ModelBinding { @@ -25,7 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding BindingSource = Metadata.BindingSource, PropertyFilterProvider = Metadata.PropertyFilterProvider, }; - + Services = GetServices(); } public TestModelBinderProviderContext(ModelMetadata metadata, BindingInfo bindingInfo) @@ -40,6 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding }; MetadataProvider = CachedMetadataProvider; + Services = GetServices(); } public override BindingInfo BindingInfo { get; } @@ -48,6 +52,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public override IModelMetadataProvider MetadataProvider { get; } + public override IServiceProvider Services { get; } + public override IModelBinder CreateBinder(ModelMetadata metadata) { foreach (var creator in _binderCreators) @@ -71,5 +77,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding { _binderCreators.Add((m) => m.Equals(metadata) ? binderCreator() : null); } + + private static IServiceProvider GetServices() + { + var services = new ServiceCollection(); + services.AddSingleton(); + return services.BuildServiceProvider(); + } } } diff --git a/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ActionParametersIntegrationTest.cs b/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ActionParametersIntegrationTest.cs index d8521ee52c..8b24b6d273 100644 --- a/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ActionParametersIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ActionParametersIntegrationTest.cs @@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Microsoft.AspNetCore.Mvc.IntegrationTests @@ -757,7 +758,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests private class CustomComplexTypeModelBinder : ComplexTypeModelBinder { public CustomComplexTypeModelBinder(IDictionary propertyBinders) - : base(propertyBinders) + : base(propertyBinders, NullLoggerFactory.Instance) { } diff --git a/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ModelBindingTestHelper.cs b/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ModelBindingTestHelper.cs index 634c9547be..0285f79a63 100644 --- a/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ModelBindingTestHelper.cs +++ b/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ModelBindingTestHelper.cs @@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.Options; @@ -77,19 +78,22 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests return new ParameterBinder( metadataProvider, GetModelBinderFactory(metadataProvider, options), - new CompositeModelValidatorProvider(GetModelValidatorProviders(options))); + new CompositeModelValidatorProvider(GetModelValidatorProviders(options)), + NullLoggerFactory.Instance); } public static IModelBinderFactory GetModelBinderFactory( IModelMetadataProvider metadataProvider, IOptions options = null) { + var services = GetServices(); + if (options == null) { - options = GetServices().GetRequiredService>(); + options = services.GetRequiredService>(); } - return new ModelBinderFactory(metadataProvider, options); + return new ModelBinderFactory(metadataProvider, options, services); } public static IObjectModelValidator GetObjectValidator( diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerProviderTest.cs index 34acdef27b..1f8eb972e1 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerProviderTest.cs @@ -479,7 +479,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var parameterBinder = new ParameterBinder( modelMetadataProvider, TestModelBinderFactory.CreateDefault(), - Mock.Of()); + Mock.Of(), + NullLoggerFactory.Instance); return new PageActionInvokerProvider( loader, diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerTest.cs index a1d066ebeb..eecbd3c7fb 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerTest.cs @@ -1238,7 +1238,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal return new ParameterBinder( TestModelMetadataProvider.CreateDefaultProvider(), factory, - validator); + validator, + NullLoggerFactory.Instance); } private static IModelValidatorProvider CreateMockValidatorProvider() diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PagePropertyBinderFactoryTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PagePropertyBinderFactoryTest.cs index 5427b649ac..7b970b6efe 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PagePropertyBinderFactoryTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PagePropertyBinderFactoryTest.cs @@ -10,6 +10,9 @@ using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -29,7 +32,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var binder = new ParameterBinder( modelMetadataProvider, TestModelBinderFactory.CreateDefault(), - Mock.Of()); + Mock.Of(), + NullLoggerFactory.Instance); // Act var factory = PagePropertyBinderFactory.CreateBinder(binder, modelMetadataProvider, actionDescriptor); @@ -52,7 +56,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var binder = new ParameterBinder( TestModelMetadataProvider.CreateDefaultProvider(), TestModelBinderFactory.CreateDefault(), - Mock.Of()); + Mock.Of(), + NullLoggerFactory.Instance); // Act var factory = PagePropertyBinderFactory.CreateBinder(binder, modelMetadataProvider, actionDescriptor); @@ -73,7 +78,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var binder = new ParameterBinder( modelMetadataProvider, TestModelBinderFactory.CreateDefault(), - Mock.Of()); + Mock.Of(), + NullLoggerFactory.Instance); // Act var factory = PagePropertyBinderFactory.CreateBinder(binder, modelMetadataProvider, actionDescriptor); @@ -95,7 +101,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var binder = new ParameterBinder( modelMetadataProvider, TestModelBinderFactory.CreateDefault(), - Mock.Of()); + Mock.Of(), + NullLoggerFactory.Instance); // Act var factory = PagePropertyBinderFactory.CreateBinder(binder, modelMetadataProvider, actionDescriptor); @@ -116,7 +123,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var binder = new ParameterBinder( modelMetadataProvider, TestModelBinderFactory.CreateDefault(), - Mock.Of()); + Mock.Of(), + NullLoggerFactory.Instance); // Act var factory = PagePropertyBinderFactory.CreateBinder(binder, modelMetadataProvider, actionDescriptor); @@ -138,7 +146,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var binder = new ParameterBinder( modelMetadataProvider, TestModelBinderFactory.CreateDefault(), - Mock.Of()); + Mock.Of(), + NullLoggerFactory.Instance); // Act var factory = PagePropertyBinderFactory.CreateBinder(binder, modelMetadataProvider, actionDescriptor); @@ -155,7 +164,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var actionDescriptor = new CompiledPageActionDescriptor { - BoundProperties = new [] + BoundProperties = new[] { new PageBoundPropertyDescriptor() { @@ -192,10 +201,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var page = new PageWithProperty { - PageContext = new PageContext() - { - HttpContext = new DefaultHttpContext(), - }, + PageContext = GetPageContext(), }; // Act @@ -253,10 +259,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var page = new PageWithProperty { - PageContext = new PageContext() - { - HttpContext = new DefaultHttpContext(), - } + PageContext = GetPageContext() }; var model = new PageModelWithProperty(); @@ -304,10 +307,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var page = new PageWithProperty { - PageContext = new PageContext() - { - HttpContext = new DefaultHttpContext(), - } + PageContext = GetPageContext() }; var model = new PageModelWithDefaultValue(); @@ -368,16 +368,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var page = new PageWithProperty { - PageContext = new PageContext() - { - HttpContext = new DefaultHttpContext() - { - Request= - { - Method = method, - } - } - } + PageContext = GetPageContext(method) }; var model = new PageModelWithSupportsGetProperty(); @@ -434,10 +425,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var page = new PageWithProperty { - PageContext = new PageContext() - { - HttpContext = new DefaultHttpContext(), - } + PageContext = GetPageContext() }; page.HttpContext.Request.Method = "Post"; @@ -452,6 +440,27 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal Assert.Equal("value", model.Default); } + private PageContext GetPageContext(string httpMethod = null) + { + var services = new ServiceCollection(); + services.AddSingleton(NullLoggerFactory.Instance); + + var httpContext = new DefaultHttpContext() + { + RequestServices = services.BuildServiceProvider() + }; + + if (httpMethod != null) + { + httpContext.Request.Method = httpMethod; + } + + return new PageContext() + { + HttpContext = httpContext + }; + } + private class TestParameterBinder : ParameterBinder { private readonly IDictionary _args; @@ -460,7 +469,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal : base( TestModelMetadataProvider.CreateDefaultProvider(), TestModelBinderFactory.CreateDefault(), - Mock.Of()) + Mock.Of(), + NullLoggerFactory.Instance) { _args = args; } diff --git a/test/Microsoft.AspNetCore.Mvc.TestCommon/Microsoft.AspNetCore.Mvc.TestCommon.csproj b/test/Microsoft.AspNetCore.Mvc.TestCommon/Microsoft.AspNetCore.Mvc.TestCommon.csproj index 72f9e5bb96..1949c7f2c8 100644 --- a/test/Microsoft.AspNetCore.Mvc.TestCommon/Microsoft.AspNetCore.Mvc.TestCommon.csproj +++ b/test/Microsoft.AspNetCore.Mvc.TestCommon/Microsoft.AspNetCore.Mvc.TestCommon.csproj @@ -13,6 +13,7 @@ + diff --git a/test/Microsoft.AspNetCore.Mvc.TestCommon/TestModelBinderFactory.cs b/test/Microsoft.AspNetCore.Mvc.TestCommon/TestModelBinderFactory.cs index 60552554fc..d524adc1ee 100644 --- a/test/Microsoft.AspNetCore.Mvc.TestCommon/TestModelBinderFactory.cs +++ b/test/Microsoft.AspNetCore.Mvc.TestCommon/TestModelBinderFactory.cs @@ -1,8 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding { @@ -36,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } public static TestModelBinderFactory CreateDefault( - IModelMetadataProvider metadataProvider, + IModelMetadataProvider metadataProvider, params IModelBinderProvider[] providers) { if (metadataProvider == null) @@ -53,9 +57,16 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return new TestModelBinderFactory(metadataProvider, options); } - protected TestModelBinderFactory(IModelMetadataProvider metadataProvider, IOptions options) - : base(metadataProvider, options) + protected TestModelBinderFactory(IModelMetadataProvider metadataProvider, IOptions options) + : base(metadataProvider, options, GetServices()) { } + + private static IServiceProvider GetServices() + { + var services = new ServiceCollection(); + services.AddSingleton(); + return services.BuildServiceProvider(); + } } }