From 708dc5cb5abd1fe0aa409f355b9e0cea8f6846d4 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sun, 16 Dec 2018 19:33:27 -0800 Subject: [PATCH] Remove many `CompatibilitySwitch` properties (#4628) - #7156 2 of 3 - will leave the `IEnumerable` implementations to avoid `breakingchanges.netcore.json` churn - will leave one `ConfigureCompatibilityOptions` subclass: `MvcOptionsConfigureCompatibilityOptions` - a few options remain as regular properties: - `ApiBehaviorOptions.SuppressMapClientErrors` (default `false`) - `MvcOptions.EnableEndpointRouting` (default `true`) - `MvcOptions.MaxValidationDepth` (default `32`) - `MvcJsonOptions.AllowInputFormatterExceptionMessages` (default `true`) nits: - move `IsEffectivePolicy(...)` check earlier in `AuthorizeFilter` - correct a typo or two --- .../DefaultApiDescriptionProvider.cs | 12 ++- .../ApiBehaviorOptions.cs | 67 +-------------- .../ApiBehaviorApplicationModelProvider.cs | 7 +- .../DefaultApplicationModelProvider.cs | 2 +- .../InferParameterBindingInfoConvention.cs | 12 +-- .../Authorization/AuthorizeFilter.cs | 42 ++++----- .../CompatibilityVersion.cs | 3 - .../ControllerBinderDelegateProvider.cs | 4 +- .../ApiBehaviorOptionsSetup.cs | 29 ++----- .../MvcCoreServiceCollectionExtensions.cs | 16 ++-- .../ControllerActionInvokerProvider.cs | 14 +-- ...MvcOptionsConfigureCompatibilityOptions.cs | 8 -- .../ModelBinding/Binders/ArrayModelBinder.cs | 11 +-- .../Binders/ArrayModelBinderProvider.cs | 4 +- .../Binders/CollectionModelBinder.cs | 12 +-- .../Binders/CollectionModelBinderProvider.cs | 4 +- .../Binders/ComplexTypeModelBinder.cs | 15 +--- .../Binders/ComplexTypeModelBinderProvider.cs | 4 +- .../Binders/DictionaryModelBinder.cs | 19 ++--- .../Binders/DictionaryModelBinderProvider.cs | 2 +- .../Binders/HeaderModelBinderProvider.cs | 18 ---- .../Metadata/DefaultModelMetadata.cs | 2 +- .../ModelBinding/ParameterBinder.cs | 6 +- .../Validation/DefaultObjectValidator.cs | 10 ++- .../MvcOptions.cs | 85 ++----------------- .../breakingchanges.netcore.json | 32 ++++++- .../MvcJsonMvcCoreBuilderExtensions.cs | 2 - ...sonOptionsConfigureCompatibilityOptions.cs | 32 ------- .../MvcJsonOptions.cs | 23 +---- .../DelegatingEnumerable.cs | 13 +-- .../DefaultPageApplicationModelProvider.cs | 5 +- .../Infrastructure/PageBinderFactory.cs | 3 +- .../DefaultApiDescriptionProviderTest.cs | 25 +----- ...ApiBehaviorApplicationModelProviderTest.cs | 13 --- ...raintForFormFileParameterConventionTest.cs | 8 +- .../DefaultApplicationModelProviderTest.cs | 59 ++----------- ...InferParameterBindingInfoConventionTest.cs | 34 +------- .../Authorization/AuthorizeFilterTest.cs | 37 ++++---- .../ControllerBinderDelegateProviderTest.cs | 55 +----------- .../ApiBehaviorOptionsSetupTest.cs | 18 +--- .../ControllerActionInvokerCacheTest.cs | 17 ++-- ...ptionsConfigureCompatibilityOptionsTest.cs | 83 ------------------ .../Binders/ArrayModelBinderProviderTest.cs | 10 +-- .../Binders/ArrayModelBinderTest.cs | 29 +------ .../CollectionModelBinderProviderTest.cs | 10 +-- .../ComplexTypeModelBinderProviderTest.cs | 11 +-- .../DictionaryModelBinderProviderTest.cs | 36 +------- .../Binders/DictionaryModelBinderTest.cs | 4 +- .../Binders/HeaderModelBinderProviderTest.cs | 54 +----------- .../Binders/HeaderModelBinderTests.cs | 44 ++++------ .../ModelBinding/ParameterBinderTest.cs | 73 +--------------- .../JsonInputFormatterTest.cs | 11 +-- .../GlobalAuthorizationFilterTest.cs | 2 +- .../AuthorizeFilterIntegrationTest.cs | 16 ++-- ...nderTypeBasedModelBinderIntegrationTest.cs | 45 ---------- .../ParameterBinderExtensions.cs | 3 +- .../TestMvcOptions.cs | 2 +- .../ValidationIntegrationTests.cs | 8 +- ...izationPageApplicationModelProviderTest.cs | 5 +- ...DefaultPageApplicationModelProviderTest.cs | 39 +-------- ...CacheFilterApplicationModelProviderTest.cs | 6 +- .../PageActionInvokerProviderTest.cs | 6 +- .../Infrastructure/PageActionInvokerTest.cs | 7 +- .../Infrastructure/PageBinderFactoryTest.cs | 73 +--------------- .../CompatibilitySwitchIntegrationTest.cs | 16 ---- .../MvcServiceCollectionExtensionsTest.cs | 7 -- .../StartupWithEndpointRouting.cs | 4 +- .../Controllers/AdministrationController.cs | 3 +- 68 files changed, 244 insertions(+), 1147 deletions(-) delete mode 100644 src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/DependencyInjection/MvcJsonOptionsConfigureCompatibilityOptions.cs delete mode 100644 src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/MvcOptionsConfigureCompatibilityOptionsTest.cs diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs index d79f2f148d..21b880b751 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs @@ -24,7 +24,6 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer public class DefaultApiDescriptionProvider : IApiDescriptionProvider { private readonly MvcOptions _mvcOptions; - private readonly IActionResultTypeMapper _mapper; private readonly ApiResponseTypeProvider _responseTypeProvider; private readonly RouteOptions _routeOptions; private readonly IInlineConstraintResolver _constraintResolver; @@ -53,7 +52,8 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// The used for resolving inline /// constraints. /// The . - /// The . + /// The . + /// The parameter is currently unused. [Obsolete("This constructor is obsolete and will be removed in a future release.")] public DefaultApiDescriptionProvider( IOptions optionsAccessor, @@ -64,7 +64,6 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer _mvcOptions = optionsAccessor.Value; _constraintResolver = constraintResolver; _modelMetadataProvider = modelMetadataProvider; - _mapper = mapper; _responseTypeProvider = new ApiResponseTypeProvider(modelMetadataProvider, mapper, _mvcOptions); } @@ -75,8 +74,9 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// The used for resolving inline /// constraints. /// The . - /// The . + /// The . /// The accessor for . + /// The parameter is currently unused. public DefaultApiDescriptionProvider( IOptions optionsAccessor, IInlineConstraintResolver constraintResolver, @@ -87,7 +87,6 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer _mvcOptions = optionsAccessor.Value; _constraintResolver = constraintResolver; _modelMetadataProvider = modelMetadataProvider; - _mapper = mapper; _responseTypeProvider = new ApiResponseTypeProvider(modelMetadataProvider, mapper, _mvcOptions); _routeOptions = routeOptions.Value; } @@ -202,8 +201,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer var visitor = new PseudoModelBindingVisitor(context, actionParameter); ModelMetadata metadata; - if (_mvcOptions.AllowValidatingTopLevelNodes && - actionParameter is ControllerParameterDescriptor controllerParameterDescriptor && + if (actionParameter is ControllerParameterDescriptor controllerParameterDescriptor && _modelMetadataProvider is ModelMetadataProvider provider) { // The default model metadata provider derives from ModelMetadataProvider diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApiBehaviorOptions.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApiBehaviorOptions.cs index 8199849002..5cd4dcf4a1 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApiBehaviorOptions.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApiBehaviorOptions.cs @@ -15,29 +15,9 @@ namespace Microsoft.AspNetCore.Mvc /// public class ApiBehaviorOptions : IEnumerable { - private readonly CompatibilitySwitch _suppressMapClientErrors; - private readonly CompatibilitySwitch _suppressUseValidationProblemDetailsForInvalidModelStateResponses; - private readonly CompatibilitySwitch _allowInferringBindingSourceForCollectionTypesAsFromQuery; - private readonly ICompatibilitySwitch[] _switches; - + private readonly ICompatibilitySwitch[] _switches = Array.Empty(); private Func _invalidModelStateResponseFactory; - /// - /// Creates a new instance of . - /// - public ApiBehaviorOptions() - { - _suppressMapClientErrors = new CompatibilitySwitch(nameof(SuppressMapClientErrors)); - _suppressUseValidationProblemDetailsForInvalidModelStateResponses = new CompatibilitySwitch(nameof(SuppressUseValidationProblemDetailsForInvalidModelStateResponses)); - _allowInferringBindingSourceForCollectionTypesAsFromQuery = new CompatibilitySwitch(nameof(AllowInferringBindingSourceForCollectionTypesAsFromQuery)); - _switches = new[] - { - _suppressMapClientErrors, - _suppressUseValidationProblemDetailsForInvalidModelStateResponses, - _allowInferringBindingSourceForCollectionTypesAsFromQuery - }; - } - /// /// Delegate invoked on actions annotated with to convert invalid /// into an @@ -92,47 +72,7 @@ namespace Microsoft.AspNetCore.Mvc /// /// The default value is . /// - public bool SuppressMapClientErrors - { - // Note: When compatibility switches are removed in 3.0, this property should be retained as a regular boolean property. - get => _suppressMapClientErrors.Value; - set => _suppressMapClientErrors.Value = value; - } - - /// - /// Gets or sets a value that determines if controllers annotated with respond using - /// in . - /// - /// When , returns errors in - /// as a . Otherwise, returns the errors - /// in the format determined by . - /// - /// - /// - /// The default value is . - /// - public bool SuppressUseValidationProblemDetailsForInvalidModelStateResponses - { - get => _suppressUseValidationProblemDetailsForInvalidModelStateResponses.Value; - set => _suppressUseValidationProblemDetailsForInvalidModelStateResponses.Value = value; - } - - /// - /// Gets or sets a value that determines if for collection types - /// (). - /// - /// When , the binding source for collection types is inferred as . - /// Otherwise is inferred. - /// - /// - /// - /// The default value is . - /// - public bool AllowInferringBindingSourceForCollectionTypesAsFromQuery - { - get => _allowInferringBindingSourceForCollectionTypesAsFromQuery.Value; - set => _allowInferringBindingSourceForCollectionTypesAsFromQuery.Value = value; - } + public bool SuppressMapClientErrors { get; set; } /// /// Gets a map of HTTP status codes to . Configured values @@ -142,8 +82,7 @@ namespace Microsoft.AspNetCore.Mvc /// Use of this feature can be disabled by resetting . /// /// - public IDictionary ClientErrorMapping { get; } = - new Dictionary(); + public IDictionary ClientErrorMapping { get; } = new Dictionary(); IEnumerator IEnumerable.GetEnumerator() { diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ApiBehaviorApplicationModelProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ApiBehaviorApplicationModelProvider.cs index d987344e85..abc14ea699 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ApiBehaviorApplicationModelProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ApiBehaviorApplicationModelProvider.cs @@ -49,12 +49,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels if (!options.SuppressInferBindingSourcesForParameters) { - var convention = new InferParameterBindingInfoConvention(modelMetadataProvider) - { - AllowInferringBindingSourceForCollectionTypesAsFromQuery = options.AllowInferringBindingSourceForCollectionTypesAsFromQuery, - }; - - ActionModelConventions.Add(convention); + ActionModelConventions.Add(new InferParameterBindingInfoConvention(modelMetadataProvider)); } } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/DefaultApplicationModelProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/DefaultApplicationModelProvider.cs index b1b23d9a93..4a74df218d 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/DefaultApplicationModelProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/DefaultApplicationModelProvider.cs @@ -454,7 +454,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels var attributes = parameterInfo.GetCustomAttributes(inherit: true); BindingInfo bindingInfo; - if (_mvcOptions.AllowValidatingTopLevelNodes && _modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) + if (_modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) { var modelMetadata = modelMetadataProviderBase.GetMetadataForParameter(parameterInfo); bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata); diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/InferParameterBindingInfoConvention.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/InferParameterBindingInfoConvention.cs index 0148be60b9..b83461b90e 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/InferParameterBindingInfoConvention.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/InferParameterBindingInfoConvention.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels /// An that infers for parameters. /// /// - /// The goal of this covention is to make intuitive and easy to document inferences. The rules are: + /// The goal of this convention is to make intuitive and easy to document inferences. The rules are: /// /// A previously specified is never overwritten. /// A complex type parameter () is assigned . @@ -31,8 +31,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels _modelMetadataProvider = modelMetadataProvider ?? throw new ArgumentNullException(nameof(modelMetadataProvider)); } - internal bool AllowInferringBindingSourceForCollectionTypesAsFromQuery { get; set; } - protected virtual bool ShouldApply(ActionModel action) => true; public void Apply(ActionModel action) @@ -118,13 +116,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels private bool IsComplexTypeParameter(ParameterModel parameter) { // No need for information from attributes on the parameter. Just use its type. - var metadata = _modelMetadataProvider - .GetMetadataForType(parameter.ParameterInfo.ParameterType); - - if (AllowInferringBindingSourceForCollectionTypesAsFromQuery && metadata.IsCollectionType) - { - return false; - } + var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterInfo.ParameterType); return metadata.IsComplexType; } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Authorization/AuthorizeFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Authorization/AuthorizeFilter.cs index df87c8d9f0..ec8d9e68e4 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Authorization/AuthorizeFilter.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Authorization/AuthorizeFilter.cs @@ -12,7 +12,6 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Mvc.Authorization { @@ -23,7 +22,6 @@ namespace Microsoft.AspNetCore.Mvc.Authorization /// public class AuthorizeFilter : IAsyncAuthorizationFilter, IFilterFactory { - private MvcOptions _mvcOptions; private AuthorizationPolicy _effectivePolicy; /// @@ -136,38 +134,25 @@ namespace Microsoft.AspNetCore.Mvc.Authorization var effectivePolicy = await ComputePolicyAsync(); var canCache = PolicyProvider == null; - if (_mvcOptions == null) + // Combine all authorize filters into single effective policy that's only run on the closest filter + var builder = new AuthorizationPolicyBuilder(effectivePolicy); + for (var i = 0; i < context.Filters.Count; i++) { - _mvcOptions = context.HttpContext.RequestServices.GetRequiredService>().Value; - } - - if (_mvcOptions.AllowCombiningAuthorizeFilters) - { - if (!context.IsEffectivePolicy(this)) + if (ReferenceEquals(this, context.Filters[i])) { - return null; + continue; } - // Combine all authorize filters into single effective policy that's only run on the closest filter - var builder = new AuthorizationPolicyBuilder(effectivePolicy); - for (var i = 0; i < context.Filters.Count; i++) + if (context.Filters[i] is AuthorizeFilter authorizeFilter) { - if (ReferenceEquals(this, context.Filters[i])) - { - continue; - } - - if (context.Filters[i] is AuthorizeFilter authorizeFilter) - { - // Combine using the explicit policy, or the dynamic policy provider - builder.Combine(await authorizeFilter.ComputePolicyAsync()); - canCache = canCache && authorizeFilter.PolicyProvider == null; - } + // Combine using the explicit policy, or the dynamic policy provider + builder.Combine(await authorizeFilter.ComputePolicyAsync()); + canCache = canCache && authorizeFilter.PolicyProvider == null; } - - effectivePolicy = builder?.Build() ?? effectivePolicy; } + effectivePolicy = builder?.Build() ?? effectivePolicy; + // We can cache the effective policy when there is no custom policy provider if (canCache) { @@ -185,6 +170,11 @@ namespace Microsoft.AspNetCore.Mvc.Authorization throw new ArgumentNullException(nameof(context)); } + if (!context.IsEffectivePolicy(this)) + { + return; + } + var effectivePolicy = await GetEffectivePolicyAsync(context); if (effectivePolicy == null) { diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs index fbd921e770..5b1dc3cf10 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs @@ -54,8 +54,6 @@ namespace Microsoft.AspNetCore.Mvc /// /// ASP.NET Core MVC 2.1 introduced compatibility switches for the following: /// - /// - /// /// /// /// MvcJsonOptions.AllowInputFormatterExceptionMessages @@ -75,7 +73,6 @@ namespace Microsoft.AspNetCore.Mvc /// ASP.NET Core MVC 2.2 introduced compatibility switches for the following: /// /// ApiBehaviorOptions.SuppressMapClientErrors - /// ApiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses /// MvcDataAnnotationsLocalizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes /// /// diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Controllers/ControllerBinderDelegateProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Controllers/ControllerBinderDelegateProvider.cs index bceb513944..fcb0cd0d11 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Controllers/ControllerBinderDelegateProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Controllers/ControllerBinderDelegateProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.ModelBinding; namespace Microsoft.AspNetCore.Mvc.Controllers @@ -134,8 +133,7 @@ namespace Microsoft.AspNetCore.Mvc.Controllers var parameter = parameters[i]; ModelMetadata metadata; - if (mvcOptions.AllowValidatingTopLevelNodes && - modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase && + if (modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase && parameter is ControllerParameterDescriptor controllerParameterDescriptor) { // The default model metadata provider derives from ModelMetadataProvider diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/ApiBehaviorOptionsSetup.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/ApiBehaviorOptionsSetup.cs index d29e5c5872..3ed6a3eeef 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/ApiBehaviorOptionsSetup.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/ApiBehaviorOptionsSetup.cs @@ -2,37 +2,21 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection { internal class ApiBehaviorOptionsSetup : - ConfigureCompatibilityOptions, - IConfigureOptions + IConfigureOptions, + IPostConfigureOptions { internal static readonly Func DefaultFactory = DefaultInvalidModelStateResponse; - internal static readonly Func ProblemDetailsFactory = ProblemDetailsInvalidModelStateResponse; - - public ApiBehaviorOptionsSetup( - ILoggerFactory loggerFactory, - IOptions compatibilityOptions) - : base(loggerFactory, compatibilityOptions) - { - } - - protected override IReadOnlyDictionary DefaultValues - { - get - { - return new Dictionary(); - } - } + internal static readonly Func ProblemDetailsFactory = + ProblemDetailsInvalidModelStateResponse; public void Configure(ApiBehaviorOptions options) { @@ -45,11 +29,8 @@ namespace Microsoft.Extensions.DependencyInjection ConfigureClientErrorMapping(options); } - public override void PostConfigure(string name, ApiBehaviorOptions options) + public void PostConfigure(string name, ApiBehaviorOptions options) { - // Let compatibility switches do their thing. - base.PostConfigure(name, options); - // We want to use problem details factory only if // (a) it has not been opted out of (SuppressMapClientErrors = true) // (b) a different factory was configured diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs index 8ea71b7178..c43eb07243 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs @@ -30,18 +30,18 @@ namespace Microsoft.Extensions.DependencyInjection { /// /// Adds the minimum essential MVC services to the specified . Additional services - /// including MVC's support for authorization, formatters, and validation must be added separately using the + /// including MVC's support for authorization, formatters, and validation must be added separately using the /// returned from this method. /// /// The to add services to. /// An that can be used to further configure the MVC services. /// /// The approach for configuring - /// MVC is provided for experienced MVC developers who wish to have full control over the set of default services + /// MVC is provided for experienced MVC developers who wish to have full control over the set of default services /// registered. will register - /// the minimum set of services necessary to route requests and invoke controllers. It is not expected that any + /// the minimum set of services necessary to route requests and invoke controllers. It is not expected that any /// application will satisfy its requirements with just a call to - /// . Additional configuration using the + /// . Additional configuration using the /// will be required. /// public static IMvcCoreBuilder AddMvcCore(this IServiceCollection services) @@ -100,7 +100,7 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Adds the minimum essential MVC services to the specified . Additional services - /// including MVC's support for authorization, formatters, and validation must be added separately using the + /// including MVC's support for authorization, formatters, and validation must be added separately using the /// returned from this method. /// /// The to add services to. @@ -108,11 +108,11 @@ namespace Microsoft.Extensions.DependencyInjection /// An that can be used to further configure the MVC services. /// /// The approach for configuring - /// MVC is provided for experienced MVC developers who wish to have full control over the set of default services + /// MVC is provided for experienced MVC developers who wish to have full control over the set of default services /// registered. will register - /// the minimum set of services necessary to route requests and invoke controllers. It is not expected that any + /// the minimum set of services necessary to route requests and invoke controllers. It is not expected that any /// application will satisfy its requirements with just a call to - /// . Additional configuration using the + /// . Additional configuration using the /// will be required. /// public static IMvcCoreBuilder AddMvcCore( diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/ControllerActionInvokerProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/ControllerActionInvokerProvider.cs index b05bd104dd..b01501960f 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/ControllerActionInvokerProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/ControllerActionInvokerProvider.cs @@ -49,20 +49,22 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure if (context.ActionContext.ActionDescriptor is ControllerActionDescriptor) { - var controllerContext = new ControllerContext(context.ActionContext); - // PERF: These are rarely going to be changed, so let's go copy-on-write. - controllerContext.ValueProviderFactories = new CopyOnWriteList(_valueProviderFactories); + var controllerContext = new ControllerContext(context.ActionContext) + { + // PERF: These are rarely going to be changed, so let's go copy-on-write. + ValueProviderFactories = new CopyOnWriteList(_valueProviderFactories) + }; controllerContext.ModelState.MaxAllowedErrors = _maxModelValidationErrors; - var cacheResult = _controllerActionInvokerCache.GetCachedResult(controllerContext); + var (cacheEntry, filters) = _controllerActionInvokerCache.GetCachedResult(controllerContext); var invoker = new ControllerActionInvoker( _logger, _diagnosticListener, _mapper, controllerContext, - cacheResult.cacheEntry, - cacheResult.filters); + cacheEntry, + filters); context.Result = invoker; } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/MvcOptionsConfigureCompatibilityOptions.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/MvcOptionsConfigureCompatibilityOptions.cs index b0f809c14c..19216fb3cc 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/MvcOptionsConfigureCompatibilityOptions.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/MvcOptionsConfigureCompatibilityOptions.cs @@ -23,16 +23,8 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure { return new Dictionary { - [nameof(MvcOptions.AllowCombiningAuthorizeFilters)] = true, - [nameof(MvcOptions.AllowBindingHeaderValuesToNonStringModelTypes)] = true, - [nameof(MvcOptions.AllowValidatingTopLevelNodes)] = true, [nameof(MvcOptions.InputFormatterExceptionPolicy)] = InputFormatterExceptionPolicy.MalformedInputExceptions, [nameof(MvcOptions.SuppressBindingUndefinedValueToEnumType)] = true, - [nameof(MvcOptions.EnableEndpointRouting)] = true, - - // Matches JsonSerializerSettingsProvider.DefaultMaxDepth - [nameof(MvcOptions.MaxValidationDepth)] = 32, - [nameof(MvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent)] = true, }; } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs index c884d8f685..ccfa3f6af7 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinder.cs @@ -38,10 +38,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// The for binding . /// /// The . - /// - /// The binder will not add an error for an unbound top-level model even if - /// is . - /// public ArrayModelBinder(IModelBinder elementBinder, ILoggerFactory loggerFactory) : base(elementBinder, loggerFactory) { @@ -59,11 +55,16 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// is for a top-level model, the binder /// adds a error when the model is not bound. /// + /// + /// The parameter is currently ignored. + /// is always + /// in . + /// public ArrayModelBinder( IModelBinder elementBinder, ILoggerFactory loggerFactory, bool allowValidatingTopLevelNodes) - : base(elementBinder, loggerFactory, allowValidatingTopLevelNodes) + : base(elementBinder, loggerFactory, allowValidatingTopLevelNodes: true) { } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinderProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinderProvider.cs index c08263056e..4eb195b7ab 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinderProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ArrayModelBinderProvider.cs @@ -4,7 +4,6 @@ using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -28,12 +27,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var binderType = typeof(ArrayModelBinder<>).MakeGenericType(elementType); var loggerFactory = context.Services.GetRequiredService(); - var mvcOptions = context.Services.GetRequiredService>().Value; return (IModelBinder)Activator.CreateInstance( binderType, elementBinder, loggerFactory, - mvcOptions.AllowValidatingTopLevelNodes); + true /* allowValidatingTopLevelNodes */); } return null; diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs index 881eb12992..0eaf3b92c8 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs @@ -42,12 +42,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// /// The for binding elements. /// The . - /// - /// The binder will not add an error for an unbound top-level model even if - /// is . - /// public CollectionModelBinder(IModelBinder elementBinder, ILoggerFactory loggerFactory) - : this(elementBinder, loggerFactory, allowValidatingTopLevelNodes: false) + : this(elementBinder, loggerFactory, allowValidatingTopLevelNodes: true) { } @@ -196,16 +192,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// /// The . /// - /// - /// This method should be called only when is - /// and a top-level model was not bound. - /// - /// /// For back-compatibility reasons, must have /// equal to when a /// top-level model is not bound. Therefore, ParameterBinder can not detect a /// failure for collections. Add the error here. - /// /// protected void AddErrorIfBindingRequired(ModelBindingContext bindingContext) { diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinderProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinderProvider.cs index 5781289596..6e66eb602d 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinderProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinderProvider.cs @@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders binderType, elementBinder, loggerFactory, - mvcOptions.AllowValidatingTopLevelNodes); + true /* allowValidatingTopLevelNodes */); } // If the model type is IEnumerable<> then we need to know if we can assign a List<> to it, since @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders binderType, elementBinder, loggerFactory, - mvcOptions.AllowValidatingTopLevelNodes); + true /* allowValidatingTopLevelNodes */); } } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs index 2da15ed858..b44a969643 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs @@ -44,14 +44,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// The of binders to use for binding properties. /// /// The . - /// - /// The binder will not add an error for an unbound top-level model even if - /// is . - /// public ComplexTypeModelBinder( IDictionary propertyBinders, ILoggerFactory loggerFactory) - : this(propertyBinders, loggerFactory, allowValidatingTopLevelNodes: false) + : this(propertyBinders, loggerFactory, allowValidatingTopLevelNodes: true) { } @@ -67,6 +63,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// is for a top-level model, the binder /// adds a error when the model is not bound. /// + /// The parameter is currently ignored. public ComplexTypeModelBinder( IDictionary propertyBinders, ILoggerFactory loggerFactory, @@ -84,13 +81,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders _propertyBinders = propertyBinders; _logger = loggerFactory.CreateLogger(); - AllowValidatingTopLevelNodes = allowValidatingTopLevelNodes; } - // Internal for testing. - internal bool AllowValidatingTopLevelNodes { get; } - - /// public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) @@ -172,8 +164,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // 1. The top-level model has no public settable properties. // 2. All properties in a [BindRequired] model have [BindNever] or are otherwise excluded from binding. // 3. No data exists for any property. - if (AllowValidatingTopLevelNodes && - !attemptedPropertyBinding && + if (!attemptedPropertyBinding && bindingContext.IsTopLevelObject && modelMetadata.IsBindingRequired) { diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinderProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinderProvider.cs index ac8d2f13d3..21478b8677 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinderProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinderProvider.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -32,11 +31,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } var loggerFactory = context.Services.GetRequiredService(); - var mvcOptions = context.Services.GetRequiredService>().Value; return new ComplexTypeModelBinder( propertyBinders, loggerFactory, - mvcOptions.AllowValidatingTopLevelNodes); + allowValidatingTopLevelNodes: true); } return null; diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs index d060a065f8..7f8ef63d0a 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs @@ -41,10 +41,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// The for . /// The for . /// The . - /// - /// The binder will not add an error for an unbound top-level model even if - /// is . - /// public DictionaryModelBinder(IModelBinder keyBinder, IModelBinder valueBinder, ILoggerFactory loggerFactory) : base(new KeyValuePairModelBinder(keyBinder, valueBinder, loggerFactory), loggerFactory) { @@ -67,6 +63,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// is for a top-level model, the binder /// adds a error when the model is not bound. /// + /// + /// The parameter is currently ignored. + /// is always + /// in . This class ignores that + /// property and unconditionally checks for unbound top-level models with + /// . + /// public DictionaryModelBinder( IModelBinder keyBinder, IModelBinder valueBinder, @@ -84,12 +87,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } _valueBinder = valueBinder; - AllowValidatingTopLevelNodes = allowValidatingTopLevelNodes; } - // Internal for testing. - internal new bool AllowValidatingTopLevelNodes { get; } - /// public override async Task BindModelAsync(ModelBindingContext bindingContext) { @@ -121,7 +120,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { // No IEnumerableValueProvider available for the fallback approach. For example the user may have // replaced the ValueProvider with something other than a CompositeValueProvider. - if (AllowValidatingTopLevelNodes && bindingContext.IsTopLevelObject) + if (bindingContext.IsTopLevelObject) { AddErrorIfBindingRequired(bindingContext); } @@ -135,7 +134,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (keys.Count == 0) { // No entries with the expected keys. - if (AllowValidatingTopLevelNodes && bindingContext.IsTopLevelObject) + if (bindingContext.IsTopLevelObject) { AddErrorIfBindingRequired(bindingContext); } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinderProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinderProvider.cs index 4ef0c83725..6958dc7370 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinderProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinderProvider.cs @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders keyBinder, valueBinder, loggerFactory, - mvcOptions.AllowValidatingTopLevelNodes); + true /* allowValidatingTopLevelNodes */); } return null; diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinderProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinderProvider.cs index 2b885e3617..b7eefcd9ca 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinderProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinderProvider.cs @@ -4,7 +4,6 @@ using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -32,23 +31,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var loggerFactory = context.Services.GetRequiredService(); var logger = loggerFactory.CreateLogger(); - var options = context.Services.GetRequiredService>().Value; - if (!options.AllowBindingHeaderValuesToNonStringModelTypes) - { - if (modelMetadata.ModelType == typeof(string) || - modelMetadata.ElementType == typeof(string)) - { - return new HeaderModelBinder(loggerFactory); - } - else - { - logger.CannotCreateHeaderModelBinderCompatVersion_2_0(modelMetadata.ModelType); - } - - return null; - } - - if (!IsSimpleType(modelMetadata)) { logger.CannotCreateHeaderModelBinder(modelMetadata.ModelType); diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs index 277da94ddd..2c2a128e4e 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs @@ -466,7 +466,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata if (defaultModelMetadata.ValidationMetadata.HasValidators != false) { - // Either the ModelMetadata instance has some validators (HasValidators = true) or it is non-deterministic (HasValidators = null). + // Either the ModelMetadata instance has some validators (HasValidators = true) or it is non-deterministic (HasValidators = null). // In either case, assume it has validators. return true; } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs index f0129749d9..365ff54dbe 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ParameterBinder.cs @@ -19,7 +19,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding { private readonly IModelMetadataProvider _modelMetadataProvider; private readonly IModelBinderFactory _modelBinderFactory; - private readonly MvcOptions _mvcOptions; private readonly IObjectModelValidator _objectModelValidator; /// @@ -55,6 +54,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// The . /// The accessor. /// The . + /// The parameter is currently unused. public ParameterBinder( IModelMetadataProvider modelMetadataProvider, IModelBinderFactory modelBinderFactory, @@ -90,7 +90,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding _modelMetadataProvider = modelMetadataProvider; _modelBinderFactory = modelBinderFactory; _objectModelValidator = validator; - _mvcOptions = mvcOptions.Value; Logger = loggerFactory.CreateLogger(GetType()); } @@ -260,8 +259,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding var modelBindingResult = modelBindingContext.Result; - if (_mvcOptions.AllowValidatingTopLevelNodes && - _objectModelValidator is ObjectModelValidator baseObjectValidator) + if (_objectModelValidator is ObjectModelValidator baseObjectValidator) { Logger.AttemptingToValidateParameterOrProperty(parameter, metadata); diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/DefaultObjectValidator.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/DefaultObjectValidator.cs index 102634f3f4..f135beadb8 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/DefaultObjectValidator.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/DefaultObjectValidator.cs @@ -39,10 +39,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation validatorProvider, validatorCache, metadataProvider, - validationState); - - visitor.MaxValidationDepth = _mvcOptions.MaxValidationDepth; - visitor.AllowShortCircuitingValidationWhenNoValidatorsArePresent = _mvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent; + validationState) + { + MaxValidationDepth = _mvcOptions.MaxValidationDepth, + AllowShortCircuitingValidationWhenNoValidatorsArePresent = + _mvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent, + }; return visitor; } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs index 3bc6332eb3..47f747660f 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs @@ -4,14 +4,11 @@ using System; using System.Collections; using System.Collections.Generic; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; @@ -22,18 +19,14 @@ namespace Microsoft.AspNetCore.Mvc /// public class MvcOptions : IEnumerable { - private int _maxModelStateErrors = ModelStateDictionary.DefaultMaxAllowedErrors; - // See CompatibilitySwitch.cs for guide on how to implement these. - private readonly CompatibilitySwitch _allowBindingHeaderValuesToNonStringModelTypes; - private readonly CompatibilitySwitch _allowCombiningAuthorizeFilters; - private readonly CompatibilitySwitch _allowValidatingTopLevelNodes; private readonly CompatibilitySwitch _inputFormatterExceptionPolicy; private readonly CompatibilitySwitch _suppressBindingUndefinedValueToEnumType; - private readonly CompatibilitySwitch _enableEndpointRouting; - private readonly NullableCompatibilitySwitch _maxValidationDepth; private readonly CompatibilitySwitch _allowShortCircuitingValidationWhenNoValidatorsArePresent; + private readonly ICompatibilitySwitch[] _switches; + private int _maxModelStateErrors = ModelStateDictionary.DefaultMaxAllowedErrors; + private int? _maxValidationDepth = 32; /// /// Creates a new instance of . @@ -52,24 +45,14 @@ namespace Microsoft.AspNetCore.Mvc ModelValidatorProviders = new List(); ValueProviderFactories = new List(); - _allowCombiningAuthorizeFilters = new CompatibilitySwitch(nameof(AllowCombiningAuthorizeFilters)); - _allowBindingHeaderValuesToNonStringModelTypes = new CompatibilitySwitch(nameof(AllowBindingHeaderValuesToNonStringModelTypes)); - _allowValidatingTopLevelNodes = new CompatibilitySwitch(nameof(AllowValidatingTopLevelNodes)); _inputFormatterExceptionPolicy = new CompatibilitySwitch(nameof(InputFormatterExceptionPolicy), InputFormatterExceptionPolicy.AllExceptions); _suppressBindingUndefinedValueToEnumType = new CompatibilitySwitch(nameof(SuppressBindingUndefinedValueToEnumType)); - _enableEndpointRouting = new CompatibilitySwitch(nameof(EnableEndpointRouting)); - _maxValidationDepth = new NullableCompatibilitySwitch(nameof(MaxValidationDepth)); _allowShortCircuitingValidationWhenNoValidatorsArePresent = new CompatibilitySwitch(nameof(AllowShortCircuitingValidationWhenNoValidatorsArePresent)); _switches = new ICompatibilitySwitch[] { - _allowCombiningAuthorizeFilters, - _allowBindingHeaderValuesToNonStringModelTypes, - _allowValidatingTopLevelNodes, _inputFormatterExceptionPolicy, _suppressBindingUndefinedValueToEnumType, - _enableEndpointRouting, - _maxValidationDepth, _allowShortCircuitingValidationWhenNoValidatorsArePresent, }; } @@ -82,11 +65,7 @@ namespace Microsoft.AspNetCore.Mvc /// /// The default value is . /// - public bool EnableEndpointRouting - { - get => _enableEndpointRouting.Value; - set => _enableEndpointRouting.Value = value; - } + public bool EnableEndpointRouting { get; set; } = true; /// /// Gets or sets the flag which decides whether body model binding (for example, on an @@ -100,58 +79,6 @@ namespace Microsoft.AspNetCore.Mvc /// public bool AllowEmptyInputInBodyModelBinding { get; set; } - /// - /// Gets or sets a value that determines if policies on instances of - /// will be combined into a single effective policy. - /// - /// - /// The default value is . - /// - /// - /// Authorization policies are designed such that multiple authorization policies applied to an endpoint - /// should be combined and executed a single policy. The (commonly applied - /// by ) can be applied globally, to controllers, and to actions - which - /// specifies multiple authorization policies for an action. In all ASP.NET Core releases prior to 2.1 - /// these multiple policies would not combine as intended. This compatibility switch configures whether the - /// old (unintended) behavior or the new combining behavior will be used when multiple authorization policies - /// are applied. - /// - public bool AllowCombiningAuthorizeFilters - { - get => _allowCombiningAuthorizeFilters.Value; - set => _allowCombiningAuthorizeFilters.Value = value; - } - - /// - /// Gets or sets a value that determines if should bind to types other than - /// or a collection of . If set to true, - /// would bind to simple types (like , , - /// , etc.) or a collection of simple types. - /// - /// - /// The default value is . - /// - public bool AllowBindingHeaderValuesToNonStringModelTypes - { - get => _allowBindingHeaderValuesToNonStringModelTypes.Value; - set => _allowBindingHeaderValuesToNonStringModelTypes.Value = value; - } - - /// - /// Gets or sets a value that determines if model bound action parameters, controller properties, page handler - /// parameters, or page model properties are validated (in addition to validating their elements or - /// properties). If set to , and - /// ValidationAttributes on these top-level nodes are checked. Otherwise, such attributes are ignored. - /// - /// - /// The default value is . - /// - public bool AllowValidatingTopLevelNodes - { - get => _allowValidatingTopLevelNodes.Value; - set => _allowValidatingTopLevelNodes.Value = value; - } - /// /// Gets a Dictionary of CacheProfile Names, which are pre-defined settings for /// response caching. @@ -311,7 +238,7 @@ namespace Microsoft.AspNetCore.Mvc /// public int? MaxValidationDepth { - get => _maxValidationDepth.Value; + get => _maxValidationDepth; set { if (value != null && value <= 0) @@ -319,7 +246,7 @@ namespace Microsoft.AspNetCore.Mvc throw new ArgumentOutOfRangeException(nameof(value)); } - _maxValidationDepth.Value = value; + _maxValidationDepth = value; } } diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/breakingchanges.netcore.json b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/breakingchanges.netcore.json index 88e1b38758..db14204e9e 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/breakingchanges.netcore.json +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/breakingchanges.netcore.json @@ -72,5 +72,35 @@ "TypeId": "public abstract class Microsoft.AspNetCore.Mvc.ModelBinding.ObjectModelValidator : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IObjectModelValidator", "MemberId": "public abstract Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor GetValidationVisitor(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidatorProvider validatorProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidatorCache validatorCache, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider metadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary validationState)", "Kind": "Addition" + }, + { + "TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable", + "MemberId": "public System.Boolean get_AllowBindingHeaderValuesToNonStringModelTypes()", + "Kind": "Removal" + }, + { + "TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable", + "MemberId": "public System.Boolean get_AllowCombiningAuthorizeFilters()", + "Kind": "Removal" + }, + { + "TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable", + "MemberId": "public System.Boolean get_AllowValidatingTopLevelNodes()", + "Kind": "Removal" + }, + { + "TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable", + "MemberId": "public System.Void set_AllowBindingHeaderValuesToNonStringModelTypes(System.Boolean value)", + "Kind": "Removal" + }, + { + "TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable", + "MemberId": "public System.Void set_AllowCombiningAuthorizeFilters(System.Boolean value)", + "Kind": "Removal" + }, + { + "TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable", + "MemberId": "public System.Void set_AllowValidatingTopLevelNodes(System.Boolean value)", + "Kind": "Removal" } -] \ No newline at end of file +] diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/DependencyInjection/MvcJsonMvcCoreBuilderExtensions.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/DependencyInjection/MvcJsonMvcCoreBuilderExtensions.cs index 7314bb1df9..e68d565e0d 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/DependencyInjection/MvcJsonMvcCoreBuilderExtensions.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/DependencyInjection/MvcJsonMvcCoreBuilderExtensions.cs @@ -75,8 +75,6 @@ namespace Microsoft.Extensions.DependencyInjection { services.TryAddEnumerable( ServiceDescriptor.Transient, MvcJsonMvcOptionsSetup>()); - services.TryAddEnumerable( - ServiceDescriptor.Transient, MvcJsonOptionsConfigureCompatibilityOptions>()); services.TryAddEnumerable( ServiceDescriptor.Transient()); services.TryAddSingleton(); diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/DependencyInjection/MvcJsonOptionsConfigureCompatibilityOptions.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/DependencyInjection/MvcJsonOptionsConfigureCompatibilityOptions.cs deleted file mode 100644 index 314550e61e..0000000000 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/DependencyInjection/MvcJsonOptionsConfigureCompatibilityOptions.cs +++ /dev/null @@ -1,32 +0,0 @@ -// 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.Collections.Generic; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Microsoft.Extensions.DependencyInjection -{ - internal class MvcJsonOptionsConfigureCompatibilityOptions : ConfigureCompatibilityOptions - { - public MvcJsonOptionsConfigureCompatibilityOptions( - ILoggerFactory loggerFactory, - IOptions compatibilityOptions) - : base(loggerFactory, compatibilityOptions) - { - } - - protected override IReadOnlyDictionary DefaultValues - { - get - { - return new Dictionary - { - [nameof(MvcJsonOptions.AllowInputFormatterExceptionMessages)] = true, - }; - } - } - } -} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/MvcJsonOptions.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/MvcJsonOptions.cs index 2d2ce11687..a1abfbea1c 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/MvcJsonOptions.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Json/MvcJsonOptions.cs @@ -1,6 +1,7 @@ // 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 System.Collections; using System.Collections.Generic; using Microsoft.AspNetCore.Mvc.Formatters; @@ -15,21 +16,7 @@ namespace Microsoft.AspNetCore.Mvc /// public class MvcJsonOptions : IEnumerable { - private readonly CompatibilitySwitch _allowInputFormatterExceptionMessages; - private readonly ICompatibilitySwitch[] _switches; - - /// - /// Creates a new instance of . - /// - public MvcJsonOptions() - { - _allowInputFormatterExceptionMessages = new CompatibilitySwitch(nameof(AllowInputFormatterExceptionMessages)); - - _switches = new ICompatibilitySwitch[] - { - _allowInputFormatterExceptionMessages, - }; - } + private readonly ICompatibilitySwitch[] _switches = Array.Empty(); /// /// Gets or sets a flag to determine whether error messages from JSON deserialization by the @@ -44,11 +31,7 @@ namespace Microsoft.AspNetCore.Mvc /// or using . In effect, this setting controls whether clients can receive /// detailed error messages about submitted JSON data. /// - public bool AllowInputFormatterExceptionMessages - { - get => _allowInputFormatterExceptionMessages.Value; - set => _allowInputFormatterExceptionMessages.Value = value; - } + public bool AllowInputFormatterExceptionMessages { get; set; } = true; /// /// Gets the that are used by this application. diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/DelegatingEnumerable.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/DelegatingEnumerable.cs index e548794e9e..5316317e69 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/DelegatingEnumerable.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/DelegatingEnumerable.cs @@ -11,9 +11,9 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml /// /// Serializes types by delegating them through a concrete implementation. /// - /// The wrapping or original type of the + /// The wrapping or original type of the /// to proxy. - /// The type parameter of the original + /// The type parameter of the original /// to proxy. public class DelegatingEnumerable : IEnumerable { @@ -21,10 +21,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml private readonly IWrapperProvider _wrapperProvider; /// - /// Initializes a . + /// Initializes a . /// /// - /// This constructor is necessary for + /// This constructor is necessary for /// to serialize. /// public DelegatingEnumerable() @@ -64,7 +64,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml /// This type will never be used for deserialization, but we are required to implement the add /// method so that the type can be serialized. This will never be called. /// - /// The item to add. Unused. + /// The item to add. + /// Thrown unconditionally. public void Add(object item) { throw new NotImplementedException(); @@ -80,4 +81,4 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml return GetEnumerator(); } } -} \ No newline at end of file +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/DefaultPageApplicationModelProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/DefaultPageApplicationModelProvider.cs index 8e6322984b..f3502855b2 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/DefaultPageApplicationModelProvider.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/DefaultPageApplicationModelProvider.cs @@ -21,7 +21,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels private readonly PageHandlerPageFilter _pageHandlerPageFilter = new PageHandlerPageFilter(); private readonly PageHandlerResultFilter _pageHandlerResultFilter = new PageHandlerResultFilter(); private readonly IModelMetadataProvider _modelMetadataProvider; - private readonly MvcOptions _mvcOptions; private readonly RazorPagesOptions _razorPagesOptions; private readonly Func _supportsAllRequests; private readonly Func _supportsNonGetRequests; @@ -29,11 +28,9 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels public DefaultPageApplicationModelProvider( IModelMetadataProvider modelMetadataProvider, - IOptions options, IOptions razorPagesOptions) { _modelMetadataProvider = modelMetadataProvider; - _mvcOptions = options.Value; _razorPagesOptions = razorPagesOptions.Value; _supportsAllRequests = _ => true; @@ -248,7 +245,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels var attributes = parameter.GetCustomAttributes(inherit: true); BindingInfo bindingInfo; - if (_mvcOptions.AllowValidatingTopLevelNodes && _modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) + if (_modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) { var modelMetadata = modelMetadataProviderBase.GetMetadataForParameter(parameter); bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata); diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageBinderFactory.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageBinderFactory.cs index c29faad2dd..574cf6e123 100644 --- a/src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageBinderFactory.cs +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageBinderFactory.cs @@ -102,8 +102,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure { var parameter = handler.Parameters[i]; ModelMetadata metadata; - if (mvcOptions.AllowValidatingTopLevelNodes && - modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) + if (modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) { // The default model metadata provider derives from ModelMetadataProvider // and can therefore supply information about attributes applied to parameters. diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs index d69609e3a4..010d18a5b2 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs @@ -1180,25 +1180,6 @@ namespace Microsoft.AspNetCore.Mvc.Description Assert.True(parameter.ModelMetadata.IsBindingRequired); } - [Fact] - public void GetApiDescription_ParameterDescription_IsRequiredNotSet_IfNotValidatingTopLevelNodes() - { - // Arrange - var action = CreateActionDescriptor(nameof(RequiredParameter)); - - // Act - var descriptions = GetApiDescriptions(action, allowValidatingTopLevelNodes: false); - - // Assert - var description = Assert.Single(descriptions); - var parameter = Assert.Single(description.ParameterDescriptions); - Assert.Equal("name", parameter.Name); - Assert.Same(BindingSource.ModelBinding, parameter.Source); - Assert.Equal(typeof(string), parameter.Type); - Assert.False(parameter.ModelMetadata.IsRequired); - Assert.False(parameter.ModelMetadata.IsBindingRequired); - } - [Fact] public void GetApiDescription_ParameterDescription_SourceFromRouteData() { @@ -1816,15 +1797,11 @@ namespace Microsoft.AspNetCore.Mvc.Description ActionDescriptor action, List inputFormatters = null, List outputFormatters = null, - bool allowValidatingTopLevelNodes = true, RouteOptions routeOptions = null) { var context = new ApiDescriptionProviderContext(new ActionDescriptor[] { action }); - var options = new MvcOptions - { - AllowValidatingTopLevelNodes = allowValidatingTopLevelNodes, - }; + var options = new MvcOptions(); foreach (var formatter in inputFormatters ?? CreateInputFormatters()) { options.InputFormatters.Add(formatter); diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/ApiBehaviorApplicationModelProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/ApiBehaviorApplicationModelProviderTest.cs index 6abbe2b59c..d344da2c08 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/ApiBehaviorApplicationModelProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/ApiBehaviorApplicationModelProviderTest.cs @@ -169,19 +169,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels loggerFactory); } - private static ApplicationModelProviderContext GetContext( - Type type, - IModelMetadataProvider modelMetadataProvider = null) - { - var context = new ApplicationModelProviderContext(new[] { type.GetTypeInfo() }); - var mvcOptions = Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }); - modelMetadataProvider = modelMetadataProvider ?? new EmptyModelMetadataProvider(); - var provider = new DefaultApplicationModelProvider(mvcOptions, modelMetadataProvider); - provider.OnProvidersExecuting(context); - - return context; - } - private class TestApiController : ControllerBase { public IActionResult TestAction(object value) => null; diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/ConsumesConstraintForFormFileParameterConventionTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/ConsumesConstraintForFormFileParameterConventionTest.cs index 660086f1b7..7cea6db928 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/ConsumesConstraintForFormFileParameterConventionTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/ConsumesConstraintForFormFileParameterConventionTest.cs @@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels IModelMetadataProvider modelMetadataProvider = null) { var context = new ApplicationModelProviderContext(new[] { type.GetTypeInfo() }); - var mvcOptions = Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }); + var mvcOptions = Options.Create(new MvcOptions()); modelMetadataProvider = modelMetadataProvider ?? new EmptyModelMetadataProvider(); var convention = new DefaultApplicationModelProvider(mvcOptions, modelMetadataProvider); convention.OnProvidersExecuting(context); @@ -68,12 +68,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels return context; } - private static ControllerModel GetControllerModel(Type controllerType) - { - var context = GetContext(controllerType); - return Assert.Single(context.Result.Controllers); - } - private static ActionModel GetActionModel(Type controllerType, string actionName) { var context = GetContext(controllerType); diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/DefaultApplicationModelProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/DefaultApplicationModelProviderTest.cs index e747856dc4..a28985b65f 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/DefaultApplicationModelProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/DefaultApplicationModelProviderTest.cs @@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels { // Arrange var builder = new TestApplicationModelProvider( - new MvcOptions { AllowValidatingTopLevelNodes = true }, + new MvcOptions(), TestModelMetadataProvider.CreateDefaultProvider()); var typeInfo = typeof(ModelBinderController).GetTypeInfo(); @@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels { // Arrange var builder = new TestApplicationModelProvider( - new MvcOptions { AllowValidatingTopLevelNodes = true }, + new MvcOptions(), TestModelMetadataProvider.CreateDefaultProvider()); var typeInfo = typeof(ModelBinderController).GetTypeInfo(); @@ -191,57 +191,12 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels }); } - [Fact] - public void OnProvidersExecuting_AddsBindingSources_ForActionParameters_WithLegacyValidationBehavior() - { - // Arrange - var builder = new TestApplicationModelProvider( - new MvcOptions(), - TestModelMetadataProvider.CreateDefaultProvider()); - var typeInfo = typeof(ModelBinderController).GetTypeInfo(); - - var context = new ApplicationModelProviderContext(new[] { typeInfo }); - - // Act - builder.OnProvidersExecuting(context); - - // Assert - var controllerModel = Assert.Single(context.Result.Controllers); - var action = Assert.Single(controllerModel.Actions, a => a.ActionMethod.Name == nameof(ModelBinderController.PostAction)); - Assert.Collection( - action.Parameters, - parameter => - { - Assert.Equal("fromQuery", parameter.ParameterName); - Assert.Equal(BindingSource.Query, parameter.BindingInfo.BindingSource); - Assert.Same(action, parameter.Action); - - var attribute = Assert.Single(parameter.Attributes); - Assert.IsType(attribute); - }, - parameter => - { - Assert.Equal("formFileCollection", parameter.ParameterName); - // BindingSource for IFormFileCollection comes from ModelMetadata which we are not using here. - Assert.Null(parameter.BindingInfo); - Assert.Same(action, parameter.Action); - - Assert.Empty(parameter.Attributes); - }, - parameter => - { - Assert.Equal("unbound", parameter.ParameterName); - Assert.Null(parameter.BindingInfo); - Assert.Same(action, parameter.Action); - }); - } - [Fact] public void OnProvidersExecuting_InfersFormFileSourceForTypesAssignableFromIEnumerableOfFormFiles() { // Arrange var builder = new TestApplicationModelProvider( - new MvcOptions { AllowValidatingTopLevelNodes = true }, + new MvcOptions(), TestModelMetadataProvider.CreateDefaultProvider()); var typeInfo = typeof(ModelBinderController).GetTypeInfo(); @@ -286,7 +241,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels public void OnProvidersExecuting_AddsBindingSources_ForActionParameters_ReadFromModelMetadata() { // Arrange - var options = new MvcOptions { AllowValidatingTopLevelNodes = true }; + var options = new MvcOptions(); var detailsProvider = new BindingSourceMetadataProvider(typeof(Guid), BindingSource.Special); var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(new[] { detailsProvider }); @@ -1822,9 +1777,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels private class TestApplicationModelProvider : DefaultApplicationModelProvider { public TestApplicationModelProvider() - : this( - new MvcOptions { AllowValidatingTopLevelNodes = true }, - new EmptyModelMetadataProvider()) + : this(new MvcOptions(), new EmptyModelMetadataProvider()) { } @@ -1836,4 +1789,4 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels } } } -} \ No newline at end of file +} diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/InferParameterBindingInfoConventionTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/InferParameterBindingInfoConventionTest.cs index 0f6527f363..9189ae47a1 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/InferParameterBindingInfoConventionTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModels/InferParameterBindingInfoConventionTest.cs @@ -468,22 +468,6 @@ Environment.NewLine + "int b"; Assert.Same(BindingSource.Body, result); } - [Fact] - public void InferBindingSourceForParameter_ReturnsQueryForCollectionOfSimpleTypes_WhenAllowInferringBindingSourceForCollectionTypesAsFromQueryIsSet() - { - // Arrange - var actionName = nameof(ParameterBindingController.CollectionOfSimpleTypes); - var parameter = GetParameterModel(typeof(ParameterBindingController), actionName); - var convention = GetConvention(); - convention.AllowInferringBindingSourceForCollectionTypesAsFromQuery = true; - - // Act - var result = convention.InferBindingSourceForParameter(parameter); - - // Assert - Assert.Same(BindingSource.Query, result); - } - [Fact] public void InferBindingSourceForParameter_ReturnsBodyForCollectionOfComplexTypes() { @@ -499,22 +483,6 @@ Environment.NewLine + "int b"; Assert.Same(BindingSource.Body, result); } - [Fact] - public void InferBindingSourceForParameter_ReturnsQueryForCollectionOfComplexTypes_WhenAllowInferringBindingSourceForCollectionTypesAsFromQueryIsSet() - { - // Arrange - var actionName = nameof(ParameterBindingController.CollectionOfComplexTypes); - var parameter = GetParameterModel(typeof(ParameterBindingController), actionName); - var convention = GetConvention(); - convention.AllowInferringBindingSourceForCollectionTypesAsFromQuery = true; - - // Act - var result = convention.InferBindingSourceForParameter(parameter); - - // Assert - Assert.Same(BindingSource.Query, result); - } - [Fact] public void PreservesBindingSourceInference_ForFromQueryParameter_WithDefaultName() { @@ -782,7 +750,7 @@ Environment.NewLine + "int b"; IModelMetadataProvider modelMetadataProvider = null) { var context = new ApplicationModelProviderContext(new[] { type.GetTypeInfo() }); - var mvcOptions = Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }); + var mvcOptions = Options.Create(new MvcOptions()); modelMetadataProvider = modelMetadataProvider ?? new EmptyModelMetadataProvider(); var convention = new DefaultApplicationModelProvider(mvcOptions, modelMetadataProvider); convention.OnProvidersExecuting(context); diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Authorization/AuthorizeFilterTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Authorization/AuthorizeFilterTest.cs index bff47d0533..9350abb80b 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Authorization/AuthorizeFilterTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Authorization/AuthorizeFilterTest.cs @@ -31,6 +31,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization { // Arrange var authorizationContext = GetAuthorizationContext(anonymous: true); + // The type 'AuthorizeFilter' is both a filter by itself and also a filter factory. // The default filter provider first checks if a type is a filter factory and creates an instance of // this filter. @@ -38,6 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization var filterFactory = authorizeFilterFactory as IFilterFactory; var authorizeFilter = (AuthorizeFilter)filterFactory.CreateInstance( authorizationContext.HttpContext.RequestServices); + authorizationContext.Filters.Add(authorizeFilter); // Act await authorizeFilter.OnAuthorizationAsync(authorizationContext); @@ -52,6 +54,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization // Arrange var authorizeFilter = new AuthorizeFilter(new[] { new AuthorizeAttribute() }); var authorizationContext = GetAuthorizationContext(); + authorizationContext.Filters.Add(authorizeFilter); var expected = "An AuthorizationPolicy cannot be created without a valid instance of " + "IAuthorizationPolicyProvider."; @@ -67,6 +70,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization // Arrange var authorizeFilter = new AuthorizeFilter(new[] { new AuthorizeAttribute() }); var authorizationContext = GetAuthorizationContext(); + authorizationContext.Filters.Add(authorizeFilter); var expected = "An AuthorizationPolicy cannot be created without a valid instance of " + "IAuthorizationPolicyProvider."; @@ -101,6 +105,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization .Callback(() => getPolicyCount++); var authorizeFilter = new AuthorizeFilter(policyProvider.Object, new AuthorizeAttribute[] { new AuthorizeAttribute("whatever") }); var authorizationContext = GetAuthorizationContext(); + authorizationContext.Filters.Add(authorizeFilter); // Act & Assert await authorizeFilter.OnAuthorizationAsync(authorizationContext); @@ -153,6 +158,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization // Arrange var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()); var authorizationContext = GetAuthorizationContext(anonymous: true); + authorizationContext.Filters.Add(authorizeFilter); // Act await authorizeFilter.OnAuthorizationAsync(authorizationContext); @@ -223,8 +229,10 @@ namespace Microsoft.AspNetCore.Mvc.Authorization private class TestPolicyProvider : IAuthorizationPolicyProvider { - private AuthorizationPolicy _true = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build(); - private AuthorizationPolicy _false = new AuthorizationPolicyBuilder().RequireAssertion(_ => false).Build(); + private readonly AuthorizationPolicy _true = + new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build(); + private readonly AuthorizationPolicy _false = + new AuthorizationPolicyBuilder().RequireAssertion(_ => false).Build(); public int GetPolicyCalls = 0; @@ -250,7 +258,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization new AuthorizeAttribute { Policy = "true"}, new AuthorizeAttribute { Policy = "false"} }); - var authorizationContext = GetAuthorizationContext(anonymous: false, registerServices: s => s.Configure(o => o.AllowCombiningAuthorizeFilters = true)); + var authorizationContext = GetAuthorizationContext(anonymous: false); // Effective policy should fail, if both are combined authorizationContext.Filters.Add(authorizeFilter); var secondFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAssertion(a => true).Build()); @@ -269,12 +277,12 @@ namespace Microsoft.AspNetCore.Mvc.Authorization // Arrange var testProvider1 = new TestPolicyProvider(); var testProvider2 = new TestPolicyProvider(); - var authorizeFilter = new AuthorizeFilter(testProvider1, new IAuthorizeData[] + var authorizeFilter = new AuthorizeFilter(testProvider1, new IAuthorizeData[] { new AuthorizeAttribute { Policy = "true"}, new AuthorizeAttribute { Policy = "false"} }); - var authorizationContext = GetAuthorizationContext(anonymous: false, registerServices: s => s.Configure(o => o.AllowCombiningAuthorizeFilters = true)); + var authorizationContext = GetAuthorizationContext(anonymous: false); // Effective policy should fail, if both are combined authorizationContext.Filters.Add(authorizeFilter); var secondFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAssertion(a => true).Build()); @@ -304,7 +312,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization { // Arrange var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAssertion(a => true).Build()); - var authorizationContext = GetAuthorizationContext(anonymous: false, registerServices: s => s.Configure(o => o.AllowCombiningAuthorizeFilters = true)); + var authorizationContext = GetAuthorizationContext(anonymous: false); // Effective policy should fail, if both are combined authorizationContext.Filters.Add(authorizeFilter); var secondFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAssertion(a => false).Build()); @@ -322,7 +330,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization { // Arrange var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAssertion(a => false).Build()); - var authorizationContext = GetAuthorizationContext(anonymous: false, registerServices: s => s.Configure(o => o.AllowCombiningAuthorizeFilters = true)); + var authorizationContext = GetAuthorizationContext(anonymous: false); // Effective policy should fail, if both are combined authorizationContext.Filters.Add(authorizeFilter); var secondFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAssertion(a => false).Build()); @@ -340,7 +348,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization { // Arrange var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAssertion(a => true).Build()); - var authorizationContext = GetAuthorizationContext(anonymous: false, registerServices: s => s.Configure(o => o.AllowCombiningAuthorizeFilters = true)); + var authorizationContext = GetAuthorizationContext(anonymous: false); // Effective policy should fail, if both are combined authorizationContext.Filters.Add(authorizeFilter); authorizationContext.Filters.Add(new DerivedAuthorizeFilter()); @@ -354,8 +362,8 @@ namespace Microsoft.AspNetCore.Mvc.Authorization // Assert Assert.IsType(authorizationContext.Result); } - - public class DerivedAuthorizeFilter : AuthorizeFilter + + public class DerivedAuthorizeFilter : AuthorizeFilter { public DerivedAuthorizeFilter() : base(new AuthorizationPolicyBuilder().RequireAssertion(a => false).Build()) { } @@ -381,6 +389,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization // Arrange var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireRole("Wut").Build()); var authorizationContext = GetAuthorizationContext(); + authorizationContext.Filters.Add(authorizeFilter); // Act await authorizeFilter.OnAuthorizationAsync(authorizationContext); @@ -397,6 +406,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization .RequireClaim("Permission", "CanViewComment") .Build()); var authorizationContext = GetAuthorizationContext(); + authorizationContext.Filters.Add(authorizeFilter); // Act await authorizeFilter.OnAuthorizationAsync(authorizationContext); @@ -532,10 +542,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization serviceCollection.AddSingleton(auth.Object); serviceCollection.AddAuthorization(); serviceCollection.AddAuthorizationPolicyEvaluator(); - if (registerServices != null) - { - registerServices(serviceCollection); - } + registerServices?.Invoke(serviceCollection); var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -557,7 +564,7 @@ namespace Microsoft.AspNetCore.Mvc.Authorization routeData: new RouteData(), actionDescriptor: new ActionDescriptor()); - var authorizationContext = new Filters.AuthorizationFilterContext( + var authorizationContext = new AuthorizationFilterContext( actionContext, Enumerable.Empty().ToList() ); diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/ControllerBinderDelegateProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/ControllerBinderDelegateProviderTest.cs index e01d0d5880..a1bd64a817 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/ControllerBinderDelegateProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/ControllerBinderDelegateProviderTest.cs @@ -9,7 +9,6 @@ using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Abstractions; -using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -28,10 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.Controllers { public class ControllerBinderDelegateProviderTest { - private static readonly MvcOptions _options = new MvcOptions - { - AllowValidatingTopLevelNodes = true, - }; + private static readonly MvcOptions _options = new MvcOptions(); private static readonly IOptions _optionsAccessor = Options.Create(_options); [Fact] @@ -428,55 +424,6 @@ namespace Microsoft.AspNetCore.Mvc.Controllers controllerContext.ModelState["memberName"].Errors.Single().ErrorMessage); } - [Fact] - public async Task CreateBinderDelegate_Delegate_DoesNotCallValidator_IfNotValidatingTopLevelNodes() - { - // Arrange - var actionDescriptor = GetActionDescriptor(); - actionDescriptor.Parameters.Add( - new ControllerParameterDescriptor - { - Name = "foo", - ParameterType = typeof(object), - ParameterInfo = ParameterInfos.CustomValidationParameterInfo - }); - - var controllerContext = GetControllerContext(actionDescriptor); - var factory = GetModelBinderFactory("Hello"); - - var mockValidator = new Mock(); - mockValidator - .Setup(o => o.Validate(It.IsAny())) - .Returns(new[] { new ModelValidationResult("memberName", "some message") }); - - // Do not set AllowValidatingTopLevelNodes. - var mvcOptions = new MvcOptions(); - - var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); - var parameterBinder = new ParameterBinder( - modelMetadataProvider, - factory, - GetObjectValidator(modelMetadataProvider, GetModelValidatorProvider(mockValidator.Object)), - Options.Create(mvcOptions), - NullLoggerFactory.Instance); - var controller = new TestController(); - var arguments = new Dictionary(StringComparer.Ordinal); - - // Act - var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate( - parameterBinder, - factory, - modelMetadataProvider, - actionDescriptor, - mvcOptions); - - await binderDelegate(controllerContext, controller, arguments); - - // Assert - Assert.True(controllerContext.ModelState.IsValid); - mockValidator.Verify(o => o.Validate(It.IsAny()), Times.Never()); - } - [Fact] public async Task CreateBinderDelegate_Delegate_DoesNotCallValidator_IfModelBinderFails() { diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/DependencyInjection/ApiBehaviorOptionsSetupTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/DependencyInjection/ApiBehaviorOptionsSetupTest.cs index a6b60a027b..82a137bf87 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/DependencyInjection/ApiBehaviorOptionsSetupTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/DependencyInjection/ApiBehaviorOptionsSetupTest.cs @@ -6,8 +6,6 @@ using System.Diagnostics; using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Microsoft.Extensions.DependencyInjection @@ -18,9 +16,7 @@ namespace Microsoft.Extensions.DependencyInjection public void Configure_AssignsInvalidModelStateResponseFactory() { // Arrange - var optionsSetup = new ApiBehaviorOptionsSetup( - NullLoggerFactory.Instance, - Options.Options.Create(new MvcCompatibilityOptions())); + var optionsSetup = new ApiBehaviorOptionsSetup(); var options = new ApiBehaviorOptions(); // Act @@ -35,9 +31,7 @@ namespace Microsoft.Extensions.DependencyInjection { // Arrange var expected = new[] { 400, 401, 403, 404, 406, 409, 415, 422, }; - var optionsSetup = new ApiBehaviorOptionsSetup( - NullLoggerFactory.Instance, - Options.Options.Create(new MvcCompatibilityOptions())); + var optionsSetup = new ApiBehaviorOptionsSetup(); var options = new ApiBehaviorOptions(); // Act @@ -51,9 +45,7 @@ namespace Microsoft.Extensions.DependencyInjection public void PostConfigure_SetProblemDetailsModelStateResponseFactory() { // Arrange - var optionsSetup = new ApiBehaviorOptionsSetup( - NullLoggerFactory.Instance, - Options.Options.Create(new MvcCompatibilityOptions { CompatibilityVersion = CompatibilityVersion.Latest })); + var optionsSetup = new ApiBehaviorOptionsSetup(); var options = new ApiBehaviorOptions(); // Act @@ -68,9 +60,7 @@ namespace Microsoft.Extensions.DependencyInjection public void PostConfigure_DoesNotSetProblemDetailsFactory_IfValueWasModified() { // Arrange - var optionsSetup = new ApiBehaviorOptionsSetup( - NullLoggerFactory.Instance, - Options.Options.Create(new MvcCompatibilityOptions { CompatibilityVersion = CompatibilityVersion.Latest })); + var optionsSetup = new ApiBehaviorOptionsSetup(); var options = new ApiBehaviorOptions(); Func expected = _ => null; diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/ControllerActionInvokerCacheTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/ControllerActionInvokerCacheTest.cs index 3b914cc092..8b0b2603f8 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/ControllerActionInvokerCacheTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/ControllerActionInvokerCacheTest.cs @@ -33,11 +33,11 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure new[] { new DefaultFilterProvider() }); // Act - var cacheEntry1 = controllerActionInvokerCache.GetCachedResult(controllerContext); - var cacheEntry2 = controllerActionInvokerCache.GetCachedResult(controllerContext); + var (cacheEntry, filters) = controllerActionInvokerCache.GetCachedResult(controllerContext); + var (cacheEntry2, filters2) = controllerActionInvokerCache.GetCachedResult(controllerContext); // Assert - Assert.Equal(cacheEntry1.filters, cacheEntry2.filters); + Assert.Equal(filters, filters2); } [Fact] @@ -54,11 +54,11 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure new[] { new DefaultFilterProvider() }); // Act - var cacheEntry1 = controllerActionInvokerCache.GetCachedResult(controllerContext); - var cacheEntry2 = controllerActionInvokerCache.GetCachedResult(controllerContext); + var (cacheEntry, filters) = controllerActionInvokerCache.GetCachedResult(controllerContext); + var (cacheEntry2, filters2) = controllerActionInvokerCache.GetCachedResult(controllerContext); // Assert - Assert.Same(cacheEntry1.cacheEntry, cacheEntry2.cacheEntry); + Assert.Same(cacheEntry, cacheEntry2); } private class TestFilter : IFilterMetadata @@ -100,10 +100,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure new[] { controllerContext.ActionDescriptor }); var modelMetadataProvider = new EmptyModelMetadataProvider(); var modelBinderFactory = TestModelBinderFactory.CreateDefault(); - var mvcOptions = Options.Create(new MvcOptions - { - AllowValidatingTopLevelNodes = true, - }); + var mvcOptions = Options.Create(new MvcOptions()); return new ControllerActionInvokerCache( descriptorProvider, diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/MvcOptionsConfigureCompatibilityOptionsTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/MvcOptionsConfigureCompatibilityOptionsTest.cs deleted file mode 100644 index 2fd9c3792c..0000000000 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/Infrastructure/MvcOptionsConfigureCompatibilityOptionsTest.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; -using Xunit; - -namespace Microsoft.AspNetCore.Mvc.Core.Infrastructure -{ - public class MvcOptionsConfigureCompatibilityOptionsTest - { - [Fact] - public void PostConfigure_ConfiguresMaxValidationDepth() - { - // Arrange - var mvcOptions = new MvcOptions(); - var mvcCompatibilityOptions = new MvcCompatibilityOptions - { - CompatibilityVersion = CompatibilityVersion.Version_3_0, - }; - - var configureOptions = new MvcOptionsConfigureCompatibilityOptions( - NullLoggerFactory.Instance, - Options.Create(mvcCompatibilityOptions)); - - // Act - configureOptions.PostConfigure(string.Empty, mvcOptions); - - // Assert - Assert.Equal(32, mvcOptions.MaxValidationDepth); - } - - [Fact] - public void PostConfigure_DoesNotConfiguresMaxValidationDepth_WhenSetToNull() - { - // Arrange - var mvcOptions = new MvcOptions - { - MaxValidationDepth = null, - }; - var mvcCompatibilityOptions = new MvcCompatibilityOptions - { - CompatibilityVersion = CompatibilityVersion.Version_3_0, - }; - - var configureOptions = new MvcOptionsConfigureCompatibilityOptions( - NullLoggerFactory.Instance, - Options.Create(mvcCompatibilityOptions)); - - // Act - configureOptions.PostConfigure(string.Empty, mvcOptions); - - // Assert - Assert.Null(mvcOptions.MaxValidationDepth); - } - - [Fact] - public void PostConfigure_DoesNotConfiguresMaxValidationDepth_WhenSetToValue() - { - // Arrange - var expected = 13; - var mvcOptions = new MvcOptions - { - MaxValidationDepth = expected, - }; - var mvcCompatibilityOptions = new MvcCompatibilityOptions - { - CompatibilityVersion = CompatibilityVersion.Version_3_0, - }; - - var configureOptions = new MvcOptionsConfigureCompatibilityOptions( - NullLoggerFactory.Instance, - Options.Create(mvcCompatibilityOptions)); - - // Act - configureOptions.PostConfigure(string.Empty, mvcOptions); - - // Assert - Assert.Equal(expected, mvcOptions.MaxValidationDepth); - } - } -} diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderProviderTest.cs index 537dd3bf4e..c4da08f0ef 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderProviderTest.cs @@ -51,17 +51,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders Assert.IsType(typeof(ArrayModelBinder<>).MakeGenericType(modelType.GetElementType()), result); } - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Create_ForArrayType_ReturnsBinder_WithExpectedAllowValidatingTopLevelNodes( - bool allowValidatingTopLevelNodes) + [Fact] + public void Create_ForArrayType_ReturnsBinder() { // Arrange var provider = new ArrayModelBinderProvider(); var context = new TestModelBinderProviderContext(typeof(int[])); - context.MvcOptions.AllowValidatingTopLevelNodes = allowValidatingTopLevelNodes; context.OnCreatingBinder(m => { Assert.Equal(typeof(int), m.ModelType); @@ -73,7 +69,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Assert var binder = Assert.IsType>(result); - Assert.Equal(allowValidatingTopLevelNodes, binder.AllowValidatingTopLevelNodes); + Assert.True(binder.AllowValidatingTopLevelNodes); } [Fact] diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderTest.cs index 2e5143fd7f..d1edc6f577 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ArrayModelBinderTest.cs @@ -48,11 +48,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders [InlineData(false, false)] [InlineData(false, true)] [InlineData(true, false)] + [InlineData(true, true)] public async Task ArrayModelBinder_CreatesEmptyCollection_IfIsTopLevelObject( bool allowValidatingTopLevelNodes, bool isBindingRequired) { // Arrange + var expectedErrorCount = isBindingRequired ? 1 : 0; var binder = new ArrayModelBinder( new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), NullLoggerFactory.Instance, @@ -81,7 +83,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Assert Assert.Empty(Assert.IsType(bindingContext.Result.Model)); Assert.True(bindingContext.Result.IsModelSet); - Assert.Equal(0, bindingContext.ModelState.ErrorCount); + Assert.Equal(expectedErrorCount, bindingContext.ModelState.ErrorCount); } [Fact] @@ -218,30 +220,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } } - private static IModelBinder CreateIntBinder() - { - return new StubModelBinder(context => - { - var value = context.ValueProvider.GetValue(context.ModelName); - if (value != ValueProviderResult.None) - { - object valueToConvert = null; - if (value.Values.Count == 1) - { - valueToConvert = value.Values[0]; - } - else if (value.Values.Count > 1) - { - valueToConvert = value.Values.ToArray(); - } - - var model = ModelBindingHelper.ConvertTo(valueToConvert, context.ModelType, value.Culture); - return ModelBindingResult.Success(model); - } - return ModelBindingResult.Failed(); - }); - } - private static DefaultModelBindingContext GetBindingContext(IValueProvider valueProvider) { var bindingContext = CreateContext(); @@ -277,4 +255,3 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } } } - diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/CollectionModelBinderProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/CollectionModelBinderProviderTest.cs index d3ee57f216..6e233a0580 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/CollectionModelBinderProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/CollectionModelBinderProviderTest.cs @@ -66,17 +66,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders Assert.IsType>(result); } - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Create_ForSupportedType_ReturnsBinder_WithExpectedAllowValidatingTopLevelNodes( - bool allowValidatingTopLevelNodes) + [Fact] + public void Create_ForSupportedType_ReturnsBinder() { // Arrange var provider = new CollectionModelBinderProvider(); var context = new TestModelBinderProviderContext(typeof(List)); - context.MvcOptions.AllowValidatingTopLevelNodes = allowValidatingTopLevelNodes; context.OnCreatingBinder(m => { Assert.Equal(typeof(int), m.ModelType); @@ -88,7 +84,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Assert var binder = Assert.IsType>(result); - Assert.Equal(allowValidatingTopLevelNodes, binder.AllowValidatingTopLevelNodes); + Assert.True(binder.AllowValidatingTopLevelNodes); } private class Person diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ComplexTypeModelBinderProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ComplexTypeModelBinderProviderTest.cs index 45e27d4ddc..cf16416641 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ComplexTypeModelBinderProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/ComplexTypeModelBinderProviderTest.cs @@ -55,17 +55,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders Assert.IsType(result); } - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Create_ForSupportedType_ReturnsBinder_WithExpectedAllowValidatingTopLevelNodes( - bool allowValidatingTopLevelNodes) + [Fact] + public void Create_ForSupportedType_ReturnsBinder() { // Arrange var provider = new ComplexTypeModelBinderProvider(); var context = new TestModelBinderProviderContext(typeof(Person)); - context.MvcOptions.AllowValidatingTopLevelNodes = allowValidatingTopLevelNodes; context.OnCreatingBinder(m => { if (m.ModelType == typeof(int) || m.ModelType == typeof(string)) @@ -83,8 +79,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var result = provider.GetBinder(context); // Assert - var binder = Assert.IsType(result); - Assert.Equal(allowValidatingTopLevelNodes, binder.AllowValidatingTopLevelNodes); + Assert.IsType(result); } private class Person diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderProviderTest.cs index 6d7add41c7..ce740a6e80 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderProviderTest.cs @@ -57,40 +57,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders var result = provider.GetBinder(context); // Assert - Assert.IsType>(result); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Create_ForDictionaryType_ReturnsBinder_WithExpectedAllowValidatingTopLevelNodes( - bool allowValidatingTopLevelNodes) - { - // Arrange - var provider = new DictionaryModelBinderProvider(); - - var context = new TestModelBinderProviderContext(typeof(Dictionary)); - context.MvcOptions.AllowValidatingTopLevelNodes = allowValidatingTopLevelNodes; - context.OnCreatingBinder(m => - { - if (m.ModelType == typeof(KeyValuePair) || m.ModelType == typeof(string)) - { - return Mock.Of(); - } - else - { - Assert.False(true, "Not the right model type"); - return null; - } - }); - - // Act - var result = provider.GetBinder(context); - - // Assert - var binder = Assert.IsType>(result); - Assert.Equal(allowValidatingTopLevelNodes, binder.AllowValidatingTopLevelNodes); - Assert.False(((CollectionModelBinder>)binder).AllowValidatingTopLevelNodes); + var binder = Assert.IsType>(result); + Assert.False(binder.AllowValidatingTopLevelNodes); // work done in DictionaryModelBinder. } private class Person diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs index 98f50a11bf..53075ff94b 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs @@ -349,11 +349,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders [InlineData(false, false)] [InlineData(false, true)] [InlineData(true, false)] + [InlineData(true, true)] public async Task DictionaryModelBinder_CreatesEmptyCollection_IfIsTopLevelObject( bool allowValidatingTopLevelNodes, bool isBindingRequired) { // Arrange + var expectedErrorCount = isBindingRequired ? 1 : 0; var binder = new DictionaryModelBinder( new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), @@ -383,7 +385,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders // Assert Assert.Empty(Assert.IsType>(bindingContext.Result.Model)); Assert.True(bindingContext.Result.IsModelSet); - Assert.Equal(0, bindingContext.ModelState.ErrorCount); + Assert.Equal(expectedErrorCount, bindingContext.ModelState.ErrorCount); } [Fact] diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderProviderTest.cs index ac60c4b0cd..41d3ad7dcd 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderProviderTest.cs @@ -14,55 +14,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { public class HeaderModelBinderProviderTest { - [Theory] - [InlineData(typeof(string))] - [InlineData(typeof(string[]))] - [InlineData(typeof(List))] - public void Create_WhenBindingSourceIsFromHeader_ReturnsBinder_ForStringTypes_And_CompatVersion_2_0( - Type modelType) - { - // Arrange - var provider = new HeaderModelBinderProvider(); - var testBinder = Mock.Of(); - var context = GetTestModelBinderProviderContext( - modelType, - allowBindingHeaderValuesToNonStringModelTypes: false); - context.BindingInfo.BindingSource = BindingSource.Header; - - // Act - var result = provider.GetBinder(context); - - // Assert - Assert.IsType(result); - } - - [Theory] - [InlineData(typeof(int))] - [InlineData(typeof(int?))] - [InlineData(typeof(IEnumerable))] - [InlineData(typeof(double))] - [InlineData(typeof(double?))] - [InlineData(typeof(IEnumerable))] - [InlineData(typeof(CarEnumType))] - [InlineData(typeof(CarEnumType?))] - [InlineData(typeof(IEnumerable))] - public void Create_WhenBindingSourceIsFromHeader_ReturnsNull_ForNonStringTypes_And_CompatVersion_2_0( - Type modelType) - { - // Arrange - var provider = new HeaderModelBinderProvider(); - var context = GetTestModelBinderProviderContext( - modelType, - allowBindingHeaderValuesToNonStringModelTypes: false); - context.BindingInfo.BindingSource = BindingSource.Header; - - // Act - var result = provider.GetBinder(context); - - // Assert - Assert.Null(result); - } - public static TheoryData NonHeaderBindingSources { get @@ -227,13 +178,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders Assert.Null(result); } - private TestModelBinderProviderContext GetTestModelBinderProviderContext( - Type modelType, - bool allowBindingHeaderValuesToNonStringModelTypes = true) + private TestModelBinderProviderContext GetTestModelBinderProviderContext(Type modelType) { var context = new TestModelBinderProviderContext(modelType); var options = context.Services.GetRequiredService>().Value; - options.AllowBindingHeaderValuesToNonStringModelTypes = allowBindingHeaderValuesToNonStringModelTypes; return context; } diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderTests.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderTests.cs index 4b4c019ea6..171f9dac73 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderTests.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/HeaderModelBinderTests.cs @@ -22,11 +22,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { get { - var data = new TheoryData(); + var data = new TheoryData + { #pragma warning disable CS0618 - data.Add(new HeaderModelBinder()); + new HeaderModelBinder(), #pragma warning restore CS0618 - data.Add(new HeaderModelBinder(NullLoggerFactory.Instance)); + new HeaderModelBinder(NullLoggerFactory.Instance), + }; + return data; } } @@ -175,11 +178,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } [Theory] - [InlineData(typeof(CarType?), null)] - [InlineData(typeof(int?), null)] - public async Task HeaderBinder_DoesNotSetModel_ForHeaderNotPresentOnRequest( - Type modelType, - object expectedModel) + [InlineData(typeof(CarType?))] + [InlineData(typeof(int?))] + public async Task HeaderBinder_DoesNotSetModel_ForHeaderNotPresentOnRequest(Type modelType) { // Arrange var bindingContext = CreateContext(modelType); @@ -194,11 +195,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } [Theory] - [InlineData(typeof(string[]), null)] - [InlineData(typeof(IEnumerable), null)] - public async Task HeaderBinder_DoesNotCreateEmptyCollection_ForNonTopLevelObjects( - Type modelType, - object expectedModel) + [InlineData(typeof(string[]))] + [InlineData(typeof(IEnumerable))] + public async Task HeaderBinder_DoesNotCreateEmptyCollection_ForNonTopLevelObjects(Type modelType) { // Arrange var bindingContext = CreateContext(modelType); @@ -344,30 +343,21 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders Assert.Equal($"The value '{headerValues[1]}' is not valid.", entry.Errors[1].ErrorMessage); } - private static DefaultModelBindingContext CreateContext( - Type modelType, - bool allowBindingHeaderValuesToNonStringModelTypes = true) + private static DefaultModelBindingContext CreateContext(Type modelType) { - return CreateContext( - metadata: GetMetadataForType(modelType), - valueProvider: null, - allowBindingHeaderValuesToNonStringModelTypes: allowBindingHeaderValuesToNonStringModelTypes); + return CreateContext(metadata: GetMetadataForType(modelType), valueProvider: null); } private static DefaultModelBindingContext CreateContext( ModelMetadata metadata, - IValueProvider valueProvider = null, - bool allowBindingHeaderValuesToNonStringModelTypes = true) + IValueProvider valueProvider = null) { if (valueProvider == null) { valueProvider = Mock.Of(); } - var options = new MvcOptions() - { - AllowBindingHeaderValuesToNonStringModelTypes = allowBindingHeaderValuesToNonStringModelTypes - }; + var options = new MvcOptions(); var setup = new MvcCoreMvcOptionsSetup(new TestHttpRequestStreamReaderFactory()); setup.Configure(options); @@ -452,4 +442,4 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders Coupe } } -} \ No newline at end of file +} diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ParameterBinderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ParameterBinderTest.cs index 0307a9c306..ac197da2d1 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ParameterBinderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ParameterBinderTest.cs @@ -27,10 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding { public class ParameterBinderTest { - private static readonly IOptions _optionsAccessor = Options.Create(new MvcOptions - { - AllowValidatingTopLevelNodes = true, - }); + private static readonly IOptions _optionsAccessor = Options.Create(new MvcOptions()); public static TheoryData BindModelAsyncData { @@ -211,37 +208,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding actionContext.ModelState.Single().Value.Errors.Single().ErrorMessage); } - [Fact] - public async Task BindModelAsync_DoesNotEnforceTopLevelBindRequired_IfNotValidatingTopLevelNodes() - { - // Arrange - var actionContext = GetControllerContext(); - - var mockModelMetadata = CreateMockModelMetadata(); - mockModelMetadata.Setup(o => o.IsBindingRequired).Returns(true); - - // Bind attribute errors are phrased in terms of the model name, not display name - mockModelMetadata.Setup(o => o.DisplayName).Returns("Ignored Display Name"); - - // Do not set AllowValidatingTopLevelNodes. - var optionsAccessor = Options.Create(new MvcOptions()); - var parameterBinder = CreateParameterBinder(mockModelMetadata.Object, optionsAccessor: optionsAccessor); - var modelBindingResult = ModelBindingResult.Failed(); - - // Act - var result = await parameterBinder.BindModelAsync( - actionContext, - CreateMockModelBinder(modelBindingResult), - CreateMockValueProvider(), - new ParameterDescriptor { Name = "myParam", ParameterType = typeof(Person) }, - mockModelMetadata.Object, - "ignoredvalue"); - - // Assert - Assert.True(actionContext.ModelState.IsValid); - Assert.Empty(actionContext.ModelState); - } - [Fact] public async Task BindModelAsync_EnforcesTopLevelRequired() { @@ -280,43 +246,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding actionContext.ModelState.Single().Value.Errors.Single().ErrorMessage); } - [Fact] - public async Task BindModelAsync_DoesNotEnforceTopLevelRequired_IfNotValidatingTopLevelNodes() - { - // Arrange - var actionContext = GetControllerContext(); - var mockModelMetadata = CreateMockModelMetadata(); - mockModelMetadata.Setup(o => o.IsRequired).Returns(true); - mockModelMetadata.Setup(o => o.DisplayName).Returns("My Display Name"); - mockModelMetadata.Setup(o => o.ValidatorMetadata).Returns(new[] - { - new RequiredAttribute() - }); - - var validator = new DataAnnotationsModelValidator( - new ValidationAttributeAdapterProvider(), - new RequiredAttribute(), - stringLocalizer: null); - - // Do not set AllowValidatingTopLevelNodes. - var optionsAccessor = Options.Create(new MvcOptions()); - var parameterBinder = CreateParameterBinder(mockModelMetadata.Object, validator, optionsAccessor); - var modelBindingResult = ModelBindingResult.Success(null); - - // Act - var result = await parameterBinder.BindModelAsync( - actionContext, - CreateMockModelBinder(modelBindingResult), - CreateMockValueProvider(), - new ParameterDescriptor { Name = "myParam", ParameterType = typeof(Person) }, - mockModelMetadata.Object, - "ignoredvalue"); - - // Assert - Assert.True(actionContext.ModelState.IsValid); - Assert.Empty(actionContext.ModelState); - } - public static TheoryData EnforcesTopLevelRequiredDataSet { get diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs index 801faf62ff..5ce71f3fd1 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs @@ -598,17 +598,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters } [Fact] - public async Task ReadAsync_DefaultOptions_DoesNotWrapJsonInputExceptions() + public async Task ReadAsync_DoNotAllowInputFormatterExceptionMessages_DoesNotWrapJsonInputExceptions() { // Arrange - var formatter = new JsonInputFormatter( - GetLogger(), - _serializerSettings, - ArrayPool.Shared, - _objectPoolProvider, - new MvcOptions(), - new MvcJsonOptions()); - + var formatter = CreateFormatter(allowInputFormatterExceptionMessages: false); var contentBytes = Encoding.UTF8.GetBytes("{"); var httpContext = GetHttpContext(contentBytes); diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs index 01ba176748..0443d9252e 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Administration/EitherCookie"); request.Headers.Add("Cookie", cookie2); - // Act 2: Will succeed because, with AllowCombiningAuthorizeFilters true, [Authorize] allows either cookie. + // Act 2: Will succeed because [Authorize] allows either cookie. response = await Client.SendAsync(request); // Assert 2 diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/AuthorizeFilterIntegrationTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/AuthorizeFilterIntegrationTest.cs index 07520c63c3..30aa58449f 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/AuthorizeFilterIntegrationTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/AuthorizeFilterIntegrationTest.cs @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests var actionContext = new ActionContext(GetHttpContext(), new RouteData(), new ControllerActionDescriptor()); - var authorizationFilterContext = new AuthorizationFilterContext(actionContext, action.Filters); + var authorizationFilterContext = new AuthorizationFilterContext(actionContext, new[] { authorizeFilter }); // Act await authorizeFilter.OnAuthorizationAsync(authorizationFilterContext); @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests var authorizeData = action.Attributes.OfType(); var authorizeFilter = new AuthorizeFilter(policyProvider, authorizeData); - var actionContext = new ActionContext(GetHttpContext(combineAuthorize: true), new RouteData(), new ControllerActionDescriptor()); + var actionContext = new ActionContext(GetHttpContext(), new RouteData(), new ControllerActionDescriptor()); var authorizationFilterContext = new AuthorizationFilterContext(actionContext, action.Filters); @@ -89,11 +89,13 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests Assert.Equal(4, policyProvider.GetPolicyCount); } - private HttpContext GetHttpContext(bool combineAuthorize = false) + private HttpContext GetHttpContext() { - var httpContext = new DefaultHttpContext(); + var httpContext = new DefaultHttpContext + { + RequestServices = GetServices() + }; - httpContext.RequestServices = GetServices(combineAuthorize); return httpContext; } @@ -108,11 +110,11 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests return context; } - private static IServiceProvider GetServices(bool combineAuthorize) + private static IServiceProvider GetServices() { var serviceCollection = new ServiceCollection(); serviceCollection.AddAuthorization(); - serviceCollection.AddMvc(o => o.AllowCombiningAuthorizeFilters = combineAuthorize); + serviceCollection.AddMvc(); serviceCollection .AddSingleton(NullLoggerFactory.Instance) .AddTransient, Logger>() diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/BinderTypeBasedModelBinderIntegrationTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/BinderTypeBasedModelBinderIntegrationTest.cs index b35b180597..bc26e31c67 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/BinderTypeBasedModelBinderIntegrationTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/BinderTypeBasedModelBinderIntegrationTest.cs @@ -189,51 +189,6 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests Assert.NotNull(entry.RawValue); // Value is set by test model binder, no need to validate it. } - // Make sure the metadata is honored when a [ModelBinder] attribute is associated with an action parameter's - // type. This should behave identically to such an attribute on an action parameter. (Tests such as - // BindParameter_WithData_WithPrefix_GetsBound cover associating [ModelBinder] with an action parameter.) - // - // This is a regression test for aspnet/Mvc#4652 - [Theory] - [MemberData(nameof(NullAndEmptyBindingInfo))] - public async Task BinderTypeOnParameterType_WithDataEmptyPrefixAndVersion20_GetsBound( - BindingInfo bindingInfo) - { - // Arrange - var testContext = ModelBindingTestHelper.GetTestContext( - // ParameterBinder will use ModelMetadata for typeof(Address), not Parameter1's ParameterInfo. - updateOptions: options => options.AllowValidatingTopLevelNodes = false); - - var modelState = testContext.ModelState; - var parameterBinder = ModelBindingTestHelper.GetParameterBinder(testContext.HttpContext.RequestServices); - var parameter = new ParameterDescriptor - { - Name = "Parameter1", - BindingInfo = bindingInfo, - ParameterType = typeof(Address), - }; - - // Act - var modelBindingResult = await parameterBinder.BindModelAsync(parameter, testContext); - - // Assert - // ModelBindingResult - Assert.True(modelBindingResult.IsModelSet); - - // Model - var address = Assert.IsType
(modelBindingResult.Model); - Assert.Equal("SomeStreet", address.Street); - - // ModelState - Assert.True(modelState.IsValid); - var kvp = Assert.Single(modelState); - Assert.Equal("Street", kvp.Key); - var entry = kvp.Value; - Assert.NotNull(entry); - Assert.Equal(ModelValidationState.Valid, entry.ValidationState); - Assert.NotNull(entry.RawValue); // Value is set by test model binder, no need to validate it. - } - private class Person3 { [ModelBinder(BinderType = typeof(Address3ModelBinder))] diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ParameterBinderExtensions.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ParameterBinderExtensions.cs index 2cf116e039..c6f773f442 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ParameterBinderExtensions.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ParameterBinderExtensions.cs @@ -41,8 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests } ModelMetadata metadata; - if (optionsAccessor.Value.AllowValidatingTopLevelNodes && - modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase && + if (modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase && parameterInfo != null) { metadata = modelMetadataProviderBase.GetMetadataForParameter(parameterInfo); diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/TestMvcOptions.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/TestMvcOptions.cs index 9711274063..8c5904d884 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/TestMvcOptions.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/TestMvcOptions.cs @@ -50,4 +50,4 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests public MvcOptions Value { get; } } -} \ No newline at end of file +} diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ValidationIntegrationTests.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ValidationIntegrationTests.cs index 25deb2477d..f5b8266451 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ValidationIntegrationTests.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.IntegrationTests/ValidationIntegrationTests.cs @@ -1705,7 +1705,8 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests public async Task FromBody_JToken_ExcludedFromValidation() { // Arrange - var parameterBinder = ModelBindingTestHelper.GetParameterBinder(new TestMvcOptions().Value); + var options = new TestMvcOptions().Value; + var parameterBinder = ModelBindingTestHelper.GetParameterBinder(options); var parameter = new ParameterDescriptor { Name = "Parameter1", @@ -1718,11 +1719,12 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests }; var testContext = ModelBindingTestHelper.GetTestContext( - request => + updateRequest: request => { request.Body = new MemoryStream(Encoding.UTF8.GetBytes("{ message: \"Hello\" }")); request.ContentType = "application/json"; - }); + }, + mvcOptions: options); var httpContext = testContext.HttpContext; var modelState = testContext.ModelState; diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/AuthorizationPageApplicationModelProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/AuthorizationPageApplicationModelProviderTest.cs index b820add41e..99da35916a 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/AuthorizationPageApplicationModelProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/AuthorizationPageApplicationModelProviderTest.cs @@ -169,11 +169,12 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels { var defaultProvider = new DefaultPageApplicationModelProvider( TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }), Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true })); + var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo); defaultProvider.OnProvidersExecuting(context); + return context; } } -} \ No newline at end of file +} diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs index b9b0cd9548..f71f5f3738 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs @@ -881,42 +881,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels }); } - [Fact] - public void CreateHandlerMethods_WithLegacyValidationBehavior_AddsParameterDescriptors() - { - // Arrange - var provider = new DefaultPageApplicationModelProvider( - TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = false }), - Options.Create(new RazorPagesOptions())); - var typeInfo = typeof(PageWithHandlerParameters).GetTypeInfo(); - var expected = typeInfo.GetMethod(nameof(PageWithHandlerParameters.OnPost)); - var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]); - - // Act - provider.PopulateHandlerMethods(pageModel); - - // Assert - var handlerMethods = pageModel.HandlerMethods; - var handler = Assert.Single(handlerMethods); - - Assert.Collection( - handler.Parameters, - p => - { - Assert.NotNull(p.ParameterInfo); - Assert.Equal(typeof(string), p.ParameterInfo.ParameterType); - Assert.Equal("name", p.ParameterName); - }, - p => - { - Assert.NotNull(p.ParameterInfo); - Assert.Equal(typeof(int), p.ParameterInfo.ParameterType); - Assert.Equal("id", p.ParameterName); - Assert.Equal("personId", p.BindingInfo.BinderModelName); - }); - } - private class PageWithHandlerParameters { public void OnPost(string name, [ModelBinder(Name = "personId")] int id) { } @@ -1078,8 +1042,8 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels // Arrange var provider = new DefaultPageApplicationModelProvider( TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions()), Options.Create(new RazorPagesOptions())); + var typeInfo = typeof(object).GetTypeInfo(); var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, typeInfo.GetCustomAttributes(inherit: true)); @@ -1225,7 +1189,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels { return new DefaultPageApplicationModelProvider( TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }), Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true })); } } diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/ResponseCacheFilterApplicationModelProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/ResponseCacheFilterApplicationModelProviderTest.cs index 622049a8c5..0609bf66b8 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/ResponseCacheFilterApplicationModelProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/ResponseCacheFilterApplicationModelProviderTest.cs @@ -6,7 +6,6 @@ using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; @@ -145,11 +144,12 @@ namespace Microsoft.AspNetCore.Mvc.Filters { var defaultProvider = new DefaultPageApplicationModelProvider( TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions()), Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true })); + var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo); defaultProvider.OnProvidersExecuting(context); + return context; } } -} \ No newline at end of file +} diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageActionInvokerProviderTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageActionInvokerProviderTest.cs index b6b78b06ca..0133ce9ffb 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageActionInvokerProviderTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageActionInvokerProviderTest.cs @@ -5,7 +5,6 @@ using System; using System.Diagnostics; using System.Linq; using System.Reflection; -using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; @@ -461,10 +460,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var modelBinderFactory = TestModelBinderFactory.CreateDefault(); - var mvcOptions = new MvcOptions - { - AllowValidatingTopLevelNodes = true, - }; + var mvcOptions = new MvcOptions(); var parameterBinder = new ParameterBinder( modelMetadataProvider, diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageActionInvokerTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageActionInvokerTest.cs index e2930aec35..f270e195d4 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageActionInvokerTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageActionInvokerTest.cs @@ -1544,15 +1544,12 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure } var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); - var mvcOptions = new MvcOptions - { - AllowValidatingTopLevelNodes = true, - }; + var mvcOptions = new MvcOptions(); return new ParameterBinder( metadataProvider, factory, - new DefaultObjectValidator(metadataProvider, new[] { validator }, new MvcOptions()), + new DefaultObjectValidator(metadataProvider, new[] { validator }, mvcOptions), Options.Create(mvcOptions), NullLoggerFactory.Instance); } diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageBinderFactoryTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageBinderFactoryTest.cs index 040f5763be..5458d7e339 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageBinderFactoryTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/PageBinderFactoryTest.cs @@ -21,10 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure { public class PageBinderFactoryTest { - private static readonly MvcOptions _options = new MvcOptions - { - AllowValidatingTopLevelNodes = true, - }; + private static readonly MvcOptions _options = new MvcOptions(); private static readonly IOptions _optionsAccessor = Options.Create(_options); [Fact] @@ -712,56 +709,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure }); } - [Fact] - public async Task CreateHandlerBinder_DoesNotValidateTopLevelParameters_IfDisabled() - { - // Arrange - var type = typeof(PageModelWithExecutors); - var actionDescriptor = GetActionDescriptorWithHandlerMethod( - type, - nameof(PageModelWithExecutors.OnPostWithValidation)); - - // Act - - var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); - var modelBinderFactory = TestModelBinderFactory.CreateDefault(); - var mvcOptions = new MvcOptions(); - - var parameterBinder = new ParameterBinder( - modelMetadataProvider, - modelBinderFactory, - new DefaultObjectValidator( - modelMetadataProvider, - new[] { TestModelValidatorProvider.CreateDefaultProvider() }, - new MvcOptions()), - Options.Create(mvcOptions), - NullLoggerFactory.Instance); - - var factory = PageBinderFactory.CreateHandlerBinder( - parameterBinder, - modelMetadataProvider, - modelBinderFactory, - actionDescriptor, - actionDescriptor.HandlerMethods[0], - mvcOptions); - - var page = new PageWithProperty - { - PageContext = GetPageContext() - }; - - var model = new PageModelWithExecutors(); - var arguments = new Dictionary(); - - // Act - await factory(page.PageContext, arguments); - - // Assert - var modelState = page.PageContext.ModelState; - Assert.True(modelState.IsValid); - Assert.Empty(modelState); - } - private static CompiledPageActionDescriptor GetActionDescriptorWithHandlerMethod(Type type, string method) { var handlerMethodInfo = type.GetMethod(method); @@ -923,24 +870,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure public string PropertyWithNoValue { get; set; } } - private class PageModelWithModelBinderAttribute - { - [ModelBinder(BinderType = typeof(DeclarativeSecurityAction))] - public Guid PropertyWithBinderType { get; set; } - } - - private class PageModelWithPropertyFilterAttribute - { - [ModelBinder] - [TestPropertyFilterProvider] - public object PropertyWithFilter { get; set; } - } - - private class TestPropertyFilterProvider : Attribute, IPropertyFilterProvider - { - public Func PropertyFilter => _ => true; - } - private class PageModelWithDefaultValue { [ModelBinder] diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs index 865b51266d..ae7cc585a8 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs @@ -43,20 +43,12 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest var xmlOptions = services.GetRequiredService>().Value; // Assert - Assert.True(mvcOptions.AllowCombiningAuthorizeFilters); - Assert.True(mvcOptions.AllowBindingHeaderValuesToNonStringModelTypes); Assert.True(mvcOptions.SuppressBindingUndefinedValueToEnumType); Assert.Equal(InputFormatterExceptionPolicy.MalformedInputExceptions, mvcOptions.InputFormatterExceptionPolicy); - Assert.True(jsonOptions.AllowInputFormatterExceptionMessages); Assert.True(razorPagesOptions.AllowAreas); - Assert.True(mvcOptions.EnableEndpointRouting); - Assert.Equal(32, mvcOptions.MaxValidationDepth); - Assert.False(apiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses); - Assert.False(apiBehaviorOptions.SuppressMapClientErrors); Assert.True(razorPagesOptions.AllowDefaultHandlingForOptionsRequests); Assert.True(xmlOptions.AllowRfc7807CompliantProblemDetailsFormat); Assert.True(mvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent); - Assert.False(apiBehaviorOptions.AllowInferringBindingSourceForCollectionTypesAsFromQuery); } [Fact] @@ -81,20 +73,12 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest var xmlOptions = services.GetRequiredService>().Value; // Assert - Assert.True(mvcOptions.AllowCombiningAuthorizeFilters); - Assert.True(mvcOptions.AllowBindingHeaderValuesToNonStringModelTypes); Assert.True(mvcOptions.SuppressBindingUndefinedValueToEnumType); Assert.Equal(InputFormatterExceptionPolicy.MalformedInputExceptions, mvcOptions.InputFormatterExceptionPolicy); - Assert.True(jsonOptions.AllowInputFormatterExceptionMessages); Assert.True(razorPagesOptions.AllowAreas); - Assert.True(mvcOptions.EnableEndpointRouting); - Assert.Equal(32, mvcOptions.MaxValidationDepth); - Assert.False(apiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses); - Assert.False(apiBehaviorOptions.SuppressMapClientErrors); Assert.True(razorPagesOptions.AllowDefaultHandlingForOptionsRequests); Assert.True(xmlOptions.AllowRfc7807CompliantProblemDetailsFormat); Assert.True(mvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent); - Assert.False(apiBehaviorOptions.AllowInferringBindingSourceForCollectionTypesAsFromQuery); } // This just does the minimum needed to be able to resolve these options. diff --git a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs index e0c13777a3..14fa1c5322 100644 --- a/src/Mvc/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs +++ b/src/Mvc/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs @@ -389,13 +389,6 @@ namespace Microsoft.AspNetCore.Mvc typeof(RazorPagesOptionsConfigureCompatibilityOptions), } }, - { - typeof(IPostConfigureOptions), - new[] - { - typeof(MvcJsonOptionsConfigureCompatibilityOptions), - } - }, { typeof(IActionConstraintProvider), new Type[] diff --git a/src/Mvc/test/WebSites/BasicWebSite/StartupWithEndpointRouting.cs b/src/Mvc/test/WebSites/BasicWebSite/StartupWithEndpointRouting.cs index bf1e8ff394..2bce493519 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/StartupWithEndpointRouting.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/StartupWithEndpointRouting.cs @@ -16,7 +16,7 @@ namespace BasicWebSite services.AddRouting(); services.AddMvc() - .SetCompatibilityVersion(CompatibilityVersion.Latest) // this compat version enables endpoint routing + .SetCompatibilityVersion(CompatibilityVersion.Latest) .AddXmlDataContractSerializerFormatters(); services.ConfigureBaseWebSiteAuthPolicies(); @@ -45,4 +45,4 @@ namespace BasicWebSite }); } } -} \ No newline at end of file +} diff --git a/src/Mvc/test/WebSites/SecurityWebSite/Controllers/AdministrationController.cs b/src/Mvc/test/WebSites/SecurityWebSite/Controllers/AdministrationController.cs index fdd125284a..74e8e9f775 100644 --- a/src/Mvc/test/WebSites/SecurityWebSite/Controllers/AdministrationController.cs +++ b/src/Mvc/test/WebSites/SecurityWebSite/Controllers/AdministrationController.cs @@ -20,8 +20,7 @@ namespace SecurityWebSite.Controllers return Content("Administration.Index"); } - // Either cookie should allow access to this action (if AllowCombiningAuthorizeFilters is true) - // If AllowCombiningAuthorizeFilters is false, the main cookie is required. + // Either cookie should allow access to this action. [Authorize(AuthenticationSchemes = "Cookie2")] public IActionResult EitherCookie() {