commit
c7559e1ff4
|
|
@ -65,6 +65,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of <see cref="BindingInfo"/> from the given <paramref name="attributes"/>.
|
||||
/// <para>
|
||||
/// This overload does not account for <see cref="BindingInfo"/> specified via <see cref="ModelMetadata"/>. Consider using
|
||||
/// <see cref="GetBindingInfo(IEnumerable{object}, ModelMetadata)"/> overload, or <see cref="TryApplyBindingInfo(ModelMetadata)"/>
|
||||
/// on the result of this method to to get a more accurate <see cref="BindingInfo"/> instance.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="attributes">A collection of attributes which are used to construct <see cref="BindingInfo"/>
|
||||
/// </param>
|
||||
|
|
@ -134,6 +139,81 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
return isBindingInfoPresent ? bindingInfo : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of <see cref="BindingInfo"/> from the given <paramref name="attributes"/> and <paramref name="modelMetadata"/>.
|
||||
/// </summary>
|
||||
/// <param name="attributes">A collection of attributes which are used to construct <see cref="BindingInfo"/>.</param>
|
||||
/// <param name="modelMetadata">The <see cref="ModelMetadata"/>.</param>
|
||||
/// <returns>A new instance of <see cref="BindingInfo"/> if any binding metadata was discovered; otherwise or <see langword="null"/>.</returns>
|
||||
public static BindingInfo GetBindingInfo(IEnumerable<object> attributes, ModelMetadata modelMetadata)
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(attributes));
|
||||
}
|
||||
|
||||
if (modelMetadata == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelMetadata));
|
||||
}
|
||||
|
||||
var bindingInfo = GetBindingInfo(attributes);
|
||||
var isBindingInfoPresent = bindingInfo != null;
|
||||
|
||||
if (bindingInfo == null)
|
||||
{
|
||||
bindingInfo = new BindingInfo();
|
||||
}
|
||||
|
||||
isBindingInfoPresent |= bindingInfo.TryApplyBindingInfo(modelMetadata);
|
||||
|
||||
return isBindingInfoPresent ? bindingInfo : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies binding metadata from the specified <paramref name="modelMetadata"/>.
|
||||
/// <para>
|
||||
/// Uses values from <paramref name="modelMetadata"/> if no value is already available.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="modelMetadata">The <see cref="ModelMetadata"/>.</param>
|
||||
/// <returns><see langword="true"/> if any binding metadata from <paramref name="modelMetadata"/> was applied;
|
||||
/// <see langword="false"/> otherwise.</returns>
|
||||
public bool TryApplyBindingInfo(ModelMetadata modelMetadata)
|
||||
{
|
||||
if (modelMetadata == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelMetadata));
|
||||
}
|
||||
|
||||
var isBindingInfoPresent = false;
|
||||
if (BinderModelName == null && modelMetadata.BinderModelName != null)
|
||||
{
|
||||
isBindingInfoPresent = true;
|
||||
BinderModelName = modelMetadata.BinderModelName;
|
||||
}
|
||||
|
||||
if (BinderType == null && modelMetadata.BinderType != null)
|
||||
{
|
||||
isBindingInfoPresent = true;
|
||||
BinderType = modelMetadata.BinderType;
|
||||
}
|
||||
|
||||
if (BindingSource == null && modelMetadata.BindingSource != null)
|
||||
{
|
||||
isBindingInfoPresent = true;
|
||||
BindingSource = modelMetadata.BindingSource;
|
||||
}
|
||||
|
||||
if (PropertyFilterProvider == null && modelMetadata.PropertyFilterProvider != null)
|
||||
{
|
||||
isBindingInfoPresent = true;
|
||||
PropertyFilterProvider = modelMetadata.PropertyFilterProvider;
|
||||
}
|
||||
|
||||
return isBindingInfoPresent;
|
||||
}
|
||||
|
||||
private class CompositePropertyFilterProvider : IPropertyFilterProvider
|
||||
{
|
||||
private readonly IEnumerable<IPropertyFilterProvider> _providers;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
isFromRequest: false);
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="BindingSource"/> for <see cref="IFormFile"/> and <see cref="IFormCollection"/>.
|
||||
/// A <see cref="BindingSource"/> for <see cref="IFormFile"/>, <see cref="IFormCollection"/>, and <see cref="IFormFileCollection"/>.
|
||||
/// </summary>
|
||||
public static readonly BindingSource FormFile = new BindingSource(
|
||||
"FormFile",
|
||||
|
|
|
|||
|
|
@ -618,8 +618,8 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
return new ApiParameterDescriptionContext
|
||||
{
|
||||
ModelMetadata = metadata,
|
||||
BinderModelName = bindingInfo?.BinderModelName ?? metadata.BinderModelName,
|
||||
BindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource,
|
||||
BinderModelName = bindingInfo?.BinderModelName,
|
||||
BindingSource = bindingInfo?.BindingSource,
|
||||
PropertyName = propertyName ?? metadata.Name,
|
||||
};
|
||||
}
|
||||
|
|
@ -716,9 +716,11 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
{
|
||||
var propertyMetadata = modelMetadata.Properties[i];
|
||||
var key = new PropertyKey(propertyMetadata, source);
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(Enumerable.Empty<object>(), propertyMetadata);
|
||||
|
||||
var propertyContext = ApiParameterDescriptionContext.GetContext(
|
||||
propertyMetadata,
|
||||
bindingInfo: null,
|
||||
bindingInfo: bindingInfo,
|
||||
propertyName: null);
|
||||
|
||||
if (Visited.Add(key))
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
actionModel.Filters.Add(_modelStateInvalidFilter);
|
||||
}
|
||||
|
||||
private void InferParameterBindingSources(ActionModel actionModel)
|
||||
// Internal for unit testing
|
||||
internal void InferParameterBindingSources(ActionModel actionModel)
|
||||
{
|
||||
if (_modelMetadataProvider == null || _apiBehaviorOptions.SuppressInferBindingSourcesForParameters)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
|
|
@ -19,11 +18,15 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
{
|
||||
public class DefaultApplicationModelProvider : IApplicationModelProvider
|
||||
{
|
||||
private readonly ICollection<IFilterMetadata> _globalFilters;
|
||||
private readonly MvcOptions _mvcOptions;
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
|
||||
public DefaultApplicationModelProvider(IOptions<MvcOptions> mvcOptionsAccessor)
|
||||
public DefaultApplicationModelProvider(
|
||||
IOptions<MvcOptions> mvcOptionsAccessor,
|
||||
IModelMetadataProvider modelMetadataProvider)
|
||||
{
|
||||
_globalFilters = mvcOptionsAccessor.Value.Filters;
|
||||
_mvcOptions = mvcOptionsAccessor.Value;
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -37,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
foreach (var filter in _globalFilters)
|
||||
foreach (var filter in _mvcOptions.Filters)
|
||||
{
|
||||
context.Result.Filters.Add(filter);
|
||||
}
|
||||
|
|
@ -118,9 +121,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
do
|
||||
{
|
||||
routeAttributes = currentTypeInfo
|
||||
.GetCustomAttributes(inherit: false)
|
||||
.OfType<IRouteTemplateProvider>()
|
||||
.ToArray();
|
||||
.GetCustomAttributes(inherit: false)
|
||||
.OfType<IRouteTemplateProvider>()
|
||||
.ToArray();
|
||||
|
||||
if (routeAttributes.Length > 0)
|
||||
{
|
||||
|
|
@ -213,24 +216,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
throw new ArgumentNullException(nameof(propertyInfo));
|
||||
}
|
||||
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToArray() is object
|
||||
var attributes = propertyInfo.GetCustomAttributes(inherit: true);
|
||||
var propertyModel = new PropertyModel(propertyInfo, attributes);
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
if (bindingInfo != null)
|
||||
{
|
||||
propertyModel.BindingInfo = bindingInfo;
|
||||
}
|
||||
else if (IsFormFileType(propertyInfo.PropertyType))
|
||||
{
|
||||
propertyModel.BindingInfo = new BindingInfo
|
||||
{
|
||||
BindingSource = BindingSource.FormFile,
|
||||
};
|
||||
}
|
||||
|
||||
propertyModel.PropertyName = propertyInfo.Name;
|
||||
|
||||
var modelMetadata = _modelMetadataProvider.GetMetadataForProperty(propertyInfo.DeclaringType, propertyInfo.Name);
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata);
|
||||
|
||||
var propertyModel = new PropertyModel(propertyInfo, attributes)
|
||||
{
|
||||
PropertyName = propertyInfo.Name,
|
||||
BindingInfo = bindingInfo,
|
||||
};
|
||||
|
||||
return propertyModel;
|
||||
}
|
||||
|
|
@ -433,25 +429,25 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
throw new ArgumentNullException(nameof(parameterInfo));
|
||||
}
|
||||
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToArray() is object
|
||||
var attributes = parameterInfo.GetCustomAttributes(inherit: true);
|
||||
var parameterModel = new ParameterModel(parameterInfo, attributes);
|
||||
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
if (bindingInfo != null)
|
||||
BindingInfo bindingInfo;
|
||||
if (_mvcOptions.AllowValidatingTopLevelNodes && _modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase)
|
||||
{
|
||||
parameterModel.BindingInfo = bindingInfo;
|
||||
var modelMetadata = modelMetadataProviderBase.GetMetadataForParameter(parameterInfo);
|
||||
bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata);
|
||||
}
|
||||
else if (IsFormFileType(parameterInfo.ParameterType))
|
||||
else
|
||||
{
|
||||
parameterModel.BindingInfo = new BindingInfo
|
||||
{
|
||||
BindingSource = BindingSource.FormFile,
|
||||
};
|
||||
// GetMetadataForParameter should only be used if the user has opted in to the 2.1 behavior.
|
||||
bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
}
|
||||
|
||||
parameterModel.ParameterName = parameterInfo.Name;
|
||||
var parameterModel = new ParameterModel(parameterInfo, attributes)
|
||||
{
|
||||
ParameterName = parameterInfo.Name,
|
||||
BindingInfo = bindingInfo,
|
||||
};
|
||||
|
||||
return parameterModel;
|
||||
}
|
||||
|
|
@ -670,12 +666,5 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsFormFileType(Type parameterType)
|
||||
{
|
||||
return parameterType == typeof(IFormFile) ||
|
||||
parameterType == typeof(IFormFileCollection) ||
|
||||
typeof(IEnumerable<IFormFile>).IsAssignableFrom(parameterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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 System.IO;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
|
@ -76,28 +77,34 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
options.ValueProviderFactories.Add(new JQueryFormValueProviderFactory());
|
||||
|
||||
// Set up metadata providers
|
||||
|
||||
// Don't bind the Type class by default as it's expensive. A user can override this behavior
|
||||
// by altering the collection of providers.
|
||||
options.ModelMetadataDetailsProviders.Add(new ExcludeBindingMetadataProvider(typeof(Type)));
|
||||
|
||||
options.ModelMetadataDetailsProviders.Add(new DefaultBindingMetadataProvider());
|
||||
options.ModelMetadataDetailsProviders.Add(new DefaultValidationMetadataProvider());
|
||||
|
||||
options.ModelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(CancellationToken), BindingSource.Special));
|
||||
options.ModelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IFormFile), BindingSource.FormFile));
|
||||
options.ModelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IFormCollection), BindingSource.FormFile));
|
||||
ConfigureAdditionalModelMetadataDetailsProvider(options.ModelMetadataDetailsProviders);
|
||||
|
||||
// Set up validators
|
||||
options.ModelValidatorProviders.Add(new DefaultModelValidatorProvider());
|
||||
}
|
||||
|
||||
internal static void ConfigureAdditionalModelMetadataDetailsProvider(IList<IMetadataDetailsProvider> modelMetadataDetailsProviders)
|
||||
{
|
||||
// Don't bind the Type class by default as it's expensive. A user can override this behavior
|
||||
// by altering the collection of providers.
|
||||
modelMetadataDetailsProviders.Add(new ExcludeBindingMetadataProvider(typeof(Type)));
|
||||
|
||||
modelMetadataDetailsProviders.Add(new DefaultBindingMetadataProvider());
|
||||
modelMetadataDetailsProviders.Add(new DefaultValidationMetadataProvider());
|
||||
|
||||
modelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(CancellationToken), BindingSource.Special));
|
||||
modelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IFormFile), BindingSource.FormFile));
|
||||
modelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IFormCollection), BindingSource.FormFile));
|
||||
modelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IFormFileCollection), BindingSource.FormFile));
|
||||
|
||||
// Add types to be excluded from Validation
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Type)));
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Uri)));
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(CancellationToken)));
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(IFormFile)));
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(IFormCollection)));
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Stream)));
|
||||
modelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Type)));
|
||||
modelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Uri)));
|
||||
modelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(CancellationToken)));
|
||||
modelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(IFormFile)));
|
||||
modelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(IFormCollection)));
|
||||
modelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(IFormFileCollection)));
|
||||
modelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Stream)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
|
|
|||
|
|
@ -233,14 +233,18 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{
|
||||
_factory = factory;
|
||||
Metadata = factoryContext.Metadata;
|
||||
BindingInfo = new BindingInfo
|
||||
BindingInfo bindingInfo;
|
||||
if (factoryContext.BindingInfo != null)
|
||||
{
|
||||
BinderModelName = factoryContext.BindingInfo?.BinderModelName ?? Metadata.BinderModelName,
|
||||
BinderType = factoryContext.BindingInfo?.BinderType ?? Metadata.BinderType,
|
||||
BindingSource = factoryContext.BindingInfo?.BindingSource ?? Metadata.BindingSource,
|
||||
PropertyFilterProvider =
|
||||
factoryContext.BindingInfo?.PropertyFilterProvider ?? Metadata.PropertyFilterProvider,
|
||||
};
|
||||
bindingInfo = new BindingInfo(factoryContext.BindingInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
bindingInfo = new BindingInfo();
|
||||
}
|
||||
|
||||
bindingInfo.TryApplyBindingInfo(Metadata);
|
||||
BindingInfo = bindingInfo;
|
||||
|
||||
MetadataProvider = _factory._metadataProvider;
|
||||
Visited = new Dictionary<Key, IModelBinder>();
|
||||
|
|
|
|||
|
|
@ -310,10 +310,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
// This is to avoid adding validation errors for an 'empty' prefix when a simple
|
||||
// type fails to bind. The fix for #7503 uncovered this issue, and was likely the
|
||||
// original problem being worked around that regressed #7503.
|
||||
string modelName = modelBindingContext.ModelName;
|
||||
var modelName = modelBindingContext.ModelName;
|
||||
|
||||
if (string.IsNullOrEmpty(modelBindingContext.ModelName) &&
|
||||
(parameter.BindingInfo?.BinderModelName ?? metadata.BinderModelName) == null)
|
||||
parameter.BindingInfo?.BinderModelName == null)
|
||||
{
|
||||
// If we get here then this is a fallback case. The model name wasn't explicitly set
|
||||
// and we ended up with an empty prefix.
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@ using System.Runtime.CompilerServices;
|
|||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Core.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.TestCommon, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
[assembly: TypeForwardedTo(typeof(InputFormatterException))]
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||
{
|
||||
|
|
@ -17,6 +18,16 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
private const string ModelPropertyName = "Model";
|
||||
private readonly PageHandlerPageFilter _pageHandlerPageFilter = new PageHandlerPageFilter();
|
||||
private readonly PageHandlerResultFilter _pageHandlerResultFilter = new PageHandlerResultFilter();
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
private readonly MvcOptions _options;
|
||||
|
||||
public DefaultPageApplicationModelProvider(
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IOptions<MvcOptions> options)
|
||||
{
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Order => -1000;
|
||||
|
|
@ -217,9 +228,22 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
throw new ArgumentNullException(nameof(parameter));
|
||||
}
|
||||
|
||||
return new PageParameterModel(parameter, parameter.GetCustomAttributes(inherit: true))
|
||||
var attributes = parameter.GetCustomAttributes(inherit: true);
|
||||
|
||||
BindingInfo bindingInfo;
|
||||
if (_options.AllowValidatingTopLevelNodes && _modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase)
|
||||
{
|
||||
BindingInfo = BindingInfo.GetBindingInfo(parameter.GetCustomAttributes()),
|
||||
var modelMetadata = modelMetadataProviderBase.GetMetadataForParameter(parameter);
|
||||
bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata);
|
||||
}
|
||||
else
|
||||
{
|
||||
bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
}
|
||||
|
||||
return new PageParameterModel(parameter, attributes)
|
||||
{
|
||||
BindingInfo = bindingInfo,
|
||||
ParameterName = parameter.Name,
|
||||
};
|
||||
}
|
||||
|
|
@ -237,12 +261,19 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
}
|
||||
|
||||
var propertyAttributes = property.GetCustomAttributes(inherit: true);
|
||||
var handlerAttributes = property.DeclaringType.GetCustomAttributes(inherit: true);
|
||||
|
||||
// Look for binding info on the handler if nothing is specified on the property.
|
||||
// This allows BindProperty attributes on handlers to apply to properties.
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(propertyAttributes) ??
|
||||
BindingInfo.GetBindingInfo(handlerAttributes);
|
||||
var propertyMetadata = _modelMetadataProvider.GetMetadataForProperty(property.DeclaringType, property.Name);
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(propertyAttributes, propertyMetadata);
|
||||
|
||||
if (bindingInfo == null)
|
||||
{
|
||||
// Look for binding info on the handler if nothing is specified on the property.
|
||||
// This allows BindProperty attributes on handlers to apply to properties.
|
||||
var handlerType = property.DeclaringType;
|
||||
var handlerAttributes = handlerType.GetCustomAttributes(inherit: true);
|
||||
var handlerMetadata = _modelMetadataProvider.GetMetadataForType(property.DeclaringType);
|
||||
bindingInfo = BindingInfo.GetBindingInfo(handlerAttributes, handlerMetadata);
|
||||
}
|
||||
|
||||
var model = new PagePropertyModel(property, propertyAttributes)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc\Microsoft.AspNetCore.Mvc.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.TestCommon\Microsoft.AspNetCore.Mvc.TestCommon.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
// 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.Linq;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
{
|
||||
public class BindingInfoTest
|
||||
{
|
||||
[Fact]
|
||||
public void GetBindingInfo_WithAttributes_ConstructsBindingInfo()
|
||||
{
|
||||
// Arrange
|
||||
var attributes = new object[]
|
||||
{
|
||||
new FromQueryAttribute { Name = "Test" },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(bindingInfo);
|
||||
Assert.Same("Test", bindingInfo.BinderModelName);
|
||||
Assert.Same(BindingSource.Query, bindingInfo.BindingSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBindingInfo_ReadsPropertyPredicateProvider()
|
||||
{
|
||||
// Arrange
|
||||
var bindAttribute = new BindAttribute(include: "SomeProperty");
|
||||
var attributes = new object[]
|
||||
{
|
||||
bindAttribute,
|
||||
};
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(bindingInfo);
|
||||
Assert.Same(bindAttribute, bindingInfo.PropertyFilterProvider);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBindingInfo_ReadsRequestPredicateProvider()
|
||||
{
|
||||
// Arrange
|
||||
var attributes = new object[]
|
||||
{
|
||||
new BindPropertyAttribute { Name = "PropertyPrefix", SupportsGet = true, },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(bindingInfo);
|
||||
Assert.Same("PropertyPrefix", bindingInfo.BinderModelName);
|
||||
Assert.NotNull(bindingInfo.RequestPredicate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBindingInfo_ReturnsNull_IfNoBindingAttributesArePresent()
|
||||
{
|
||||
// Arrange
|
||||
var attributes = new object[] { new ControllerAttribute(), new BindNeverAttribute(), };
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
|
||||
// Assert
|
||||
Assert.Null(bindingInfo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBindingInfo_WithAttributesAndModelMetadata_UsesValuesFromBindingInfo_IfAttributesPresent()
|
||||
{
|
||||
// Arrange
|
||||
var attributes = new object[]
|
||||
{
|
||||
new ModelBinderAttribute { BinderType = typeof(object), Name = "Test" },
|
||||
};
|
||||
var modelType = typeof(Guid);
|
||||
var provider = new TestModelMetadataProvider();
|
||||
provider.ForType(modelType).BindingDetails(metadata =>
|
||||
{
|
||||
metadata.BindingSource = BindingSource.Special;
|
||||
metadata.BinderType = typeof(string);
|
||||
metadata.BinderModelName = "Different";
|
||||
});
|
||||
var modelMetadata = provider.GetMetadataForType(modelType);
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(bindingInfo);
|
||||
Assert.Same(typeof(object), bindingInfo.BinderType);
|
||||
Assert.Same("Test", bindingInfo.BinderModelName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBindingInfo_WithAttributesAndModelMetadata_UsesBinderNameFromModelMetadata_WhenNotFoundViaAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var attributes = new object[] { new ModelBinderAttribute(typeof(object)), new ControllerAttribute(), new BindNeverAttribute(), };
|
||||
var modelType = typeof(Guid);
|
||||
var provider = new TestModelMetadataProvider();
|
||||
provider.ForType(modelType).BindingDetails(metadata =>
|
||||
{
|
||||
metadata.BindingSource = BindingSource.Special;
|
||||
metadata.BinderType = typeof(string);
|
||||
metadata.BinderModelName = "Different";
|
||||
});
|
||||
var modelMetadata = provider.GetMetadataForType(modelType);
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(bindingInfo);
|
||||
Assert.Same(typeof(object), bindingInfo.BinderType);
|
||||
Assert.Same("Different", bindingInfo.BinderModelName);
|
||||
Assert.Same(BindingSource.Custom, bindingInfo.BindingSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBindingInfo_WithAttributesAndModelMetadata_UsesModelBinderFromModelMetadata_WhenNotFoundViaAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var attributes = new object[] { new ControllerAttribute(), new BindNeverAttribute(), };
|
||||
var modelType = typeof(Guid);
|
||||
var provider = new TestModelMetadataProvider();
|
||||
provider.ForType(modelType).BindingDetails(metadata =>
|
||||
{
|
||||
metadata.BinderType = typeof(string);
|
||||
});
|
||||
var modelMetadata = provider.GetMetadataForType(modelType);
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(bindingInfo);
|
||||
Assert.Same(typeof(string), bindingInfo.BinderType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBindingInfo_WithAttributesAndModelMetadata_UsesBinderSourceFromModelMetadata_WhenNotFoundViaAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var attributes = new object[] { new BindPropertyAttribute(), new ControllerAttribute(), new BindNeverAttribute(), };
|
||||
var modelType = typeof(Guid);
|
||||
var provider = new TestModelMetadataProvider();
|
||||
provider.ForType(modelType).BindingDetails(metadata =>
|
||||
{
|
||||
metadata.BindingSource = BindingSource.Services;
|
||||
});
|
||||
var modelMetadata = provider.GetMetadataForType(modelType);
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(bindingInfo);
|
||||
Assert.Same(BindingSource.Services, bindingInfo.BindingSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBindingInfo_WithAttributesAndModelMetadata_UsesPropertyPredicateProviderFromModelMetadata_WhenNotFoundViaAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var attributes = new object[] { new ModelBinderAttribute(typeof(object)), new ControllerAttribute(), new BindNeverAttribute(), };
|
||||
var modelAttributes = new ModelAttributes(Enumerable.Empty<object>(), null, null);
|
||||
var propertyFilterProvider = Mock.Of<IPropertyFilterProvider>();
|
||||
var modelType = typeof(Guid);
|
||||
var provider = new TestModelMetadataProvider();
|
||||
provider.ForType(modelType).BindingDetails(metadata =>
|
||||
{
|
||||
metadata.PropertyFilterProvider = propertyFilterProvider;
|
||||
});
|
||||
var modelMetadata = provider.GetMetadataForType(modelType);
|
||||
|
||||
// Act
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(bindingInfo);
|
||||
Assert.Same(propertyFilterProvider, bindingInfo.PropertyFilterProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
|||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
@ -790,7 +791,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
|
||||
var manager = GetApplicationManager(controllerTypes);
|
||||
|
||||
var modelProvider = new DefaultApplicationModelProvider(options);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
manager,
|
||||
|
|
@ -964,8 +965,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
{
|
||||
foreach (var item in context.Results)
|
||||
{
|
||||
var marker = item.Metadata as BooleanConstraintMarker;
|
||||
if (marker != null)
|
||||
if (item.Metadata is BooleanConstraintMarker marker)
|
||||
{
|
||||
Assert.Null(item.Constraint);
|
||||
item.Constraint = new BooleanConstraint() { Pass = marker.Pass };
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
|
|
@ -383,6 +384,31 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
Assert.Same(BindingSource.Body, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InferParameterBindingSources_SetsCorrectBindingSourceForComplexTypesWithCancellationToken()
|
||||
{
|
||||
// Arrange
|
||||
var actionName = nameof(ParameterBindingController.ComplexTypeModelWithCancellationToken);
|
||||
|
||||
// Use the default set of ModelMetadataProviders so we get metadata details for CancellationToken.
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var context = GetContext(typeof(ParameterBindingController), modelMetadataProvider);
|
||||
var controllerModel = Assert.Single(context.Result.Controllers);
|
||||
var actionModel = Assert.Single(controllerModel.Actions, m => m.ActionName == actionName);
|
||||
|
||||
var provider = GetProvider();
|
||||
|
||||
// Act
|
||||
provider.InferParameterBindingSources(actionModel);
|
||||
|
||||
// Assert
|
||||
var model = GetParameterModel<TestModel>(actionModel);
|
||||
Assert.Same(BindingSource.Body, model.BindingInfo.BindingSource);
|
||||
|
||||
var cancellationToken = GetParameterModel<CancellationToken>(actionModel);
|
||||
Assert.Same(BindingSource.Special, cancellationToken.BindingInfo.BindingSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InferBindingSourceForParameter_ReturnsBodyForSimpleTypes()
|
||||
{
|
||||
|
|
@ -503,16 +529,21 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
};
|
||||
var optionsAccessor = Options.Create(options);
|
||||
|
||||
modelMetadataProvider = modelMetadataProvider ?? new TestModelMetadataProvider();
|
||||
var loggerFactory = NullLoggerFactory.Instance;
|
||||
|
||||
modelMetadataProvider = modelMetadataProvider ?? new EmptyModelMetadataProvider();
|
||||
return new ApiBehaviorApplicationModelProvider(optionsAccessor, modelMetadataProvider, loggerFactory);
|
||||
}
|
||||
|
||||
private static ApplicationModelProviderContext GetContext(Type type)
|
||||
private static ApplicationModelProviderContext GetContext(
|
||||
Type type,
|
||||
IModelMetadataProvider modelMetadataProvider = null)
|
||||
{
|
||||
var context = new ApplicationModelProviderContext(new[] { type.GetTypeInfo() });
|
||||
new DefaultApplicationModelProvider(Options.Create(new MvcOptions())).OnProvidersExecuting(context);
|
||||
var mvcOptions = Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true });
|
||||
modelMetadataProvider = modelMetadataProvider ?? new EmptyModelMetadataProvider();
|
||||
var provider = new DefaultApplicationModelProvider(mvcOptions, modelMetadataProvider);
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -535,6 +566,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
return Assert.Single(action.Parameters);
|
||||
}
|
||||
|
||||
private static ParameterModel GetParameterModel<T>(ActionModel action)
|
||||
{
|
||||
return Assert.Single(action.Parameters.Where(x => typeof(T).IsAssignableFrom(x.ParameterType)));
|
||||
}
|
||||
|
||||
[ApiController]
|
||||
[Route("TestApi")]
|
||||
private class TestApiController : Controller
|
||||
|
|
@ -612,6 +648,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
[HttpPost]
|
||||
[Consumes("application/json")]
|
||||
public IActionResult ActionWithConsumesAttribute([FromForm] string parameter) => null;
|
||||
|
||||
[HttpPut("cancellation")]
|
||||
public IActionResult ComplexTypeModelWithCancellationToken(TestModel model, CancellationToken cancellationToken) => null;
|
||||
}
|
||||
|
||||
[ApiController]
|
||||
|
|
|
|||
|
|
@ -1,7 +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.Collections.Generic;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Authorization.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -22,10 +23,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
{
|
||||
// Arrange
|
||||
var provider = new AuthorizationApplicationModelProvider(new DefaultAuthorizationPolicyProvider(Options.Create(new AuthorizationOptions())));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(AccountController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var controllerType = typeof(AccountController);
|
||||
var context = CreateProviderContext(controllerType);
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
|
@ -44,10 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
options.Value.AddPolicy("Derived", policy => policy.RequireClaim("Derived"));
|
||||
|
||||
var provider = new AuthorizationApplicationModelProvider(new DefaultAuthorizationPolicyProvider(options));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(DerivedController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = CreateProviderContext(typeof(DerivedController));
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
|
@ -71,10 +67,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
{
|
||||
// Arrange
|
||||
var provider = new AuthorizationApplicationModelProvider(new DefaultAuthorizationPolicyProvider(Options.Create(new AuthorizationOptions())));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(AnonymousController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = CreateProviderContext(typeof(AnonymousController));
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
|
@ -100,10 +93,10 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var policyProvider = new DefaultAuthorizationPolicyProvider(authOptions);
|
||||
|
||||
var provider = new AuthorizationApplicationModelProvider(policyProvider);
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
var context = CreateProviderContext(typeof(BaseController));
|
||||
|
||||
// Act
|
||||
var action = GetBaseControllerActionModel(provider, defaultProvider);
|
||||
var action = GetBaseControllerActionModel(provider);
|
||||
|
||||
// Assert
|
||||
var authorizationFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(action.Filters));
|
||||
|
|
@ -128,10 +121,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Verifiable();
|
||||
|
||||
var provider = new AuthorizationApplicationModelProvider(authorizationPolicyProviderMock.Object);
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
// Act
|
||||
var action = GetBaseControllerActionModel(provider, defaultProvider);
|
||||
var action = GetBaseControllerActionModel(provider);
|
||||
|
||||
// Assert
|
||||
var actionFilter = Assert.IsType<AuthorizeFilter>(Assert.Single(action.Filters));
|
||||
|
|
@ -148,10 +140,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
new DefaultAuthorizationPolicyProvider(
|
||||
Options.Create(new AuthorizationOptions())
|
||||
));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(NoAuthController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = CreateProviderContext(typeof(NoAuthController));
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
|
@ -163,16 +152,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
Assert.Empty(action.Filters);
|
||||
}
|
||||
|
||||
private ActionModel GetBaseControllerActionModel(
|
||||
IApplicationModelProvider authorizationApplicationModelProvider,
|
||||
IApplicationModelProvider applicationModelProvider)
|
||||
private ActionModel GetBaseControllerActionModel(AuthorizationApplicationModelProvider authorizationApplicationModelProvider)
|
||||
{
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(BaseController).GetTypeInfo() });
|
||||
applicationModelProvider.OnProvidersExecuting(context);
|
||||
var authorizeData = new List<IAuthorizeData>
|
||||
{
|
||||
new AuthorizeAttribute("POLICY")
|
||||
};
|
||||
var context = CreateProviderContext(typeof(BaseController));
|
||||
|
||||
authorizationApplicationModelProvider.OnProvidersExecuting(context);
|
||||
|
||||
|
|
@ -183,6 +165,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
return action;
|
||||
}
|
||||
|
||||
private static ApplicationModelProviderContext CreateProviderContext(Type controllerType)
|
||||
{
|
||||
var defaultProvider = new DefaultApplicationModelProvider(
|
||||
Options.Create(new MvcOptions()),
|
||||
TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { controllerType.GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
return context;
|
||||
}
|
||||
|
||||
private class BaseController
|
||||
{
|
||||
[Authorize(Policy = "Base")]
|
||||
|
|
|
|||
|
|
@ -709,7 +709,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var manager = GetApplicationManager(new[] { controllerTypeInfo });
|
||||
var options = Options.Create(new MvcOptions());
|
||||
options.Value.Conventions.Add(new TestRoutingConvention());
|
||||
var modelProvider = new DefaultApplicationModelProvider(options);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, TestModelMetadataProvider.CreateDefaultProvider());
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
manager,
|
||||
new[] { modelProvider },
|
||||
|
|
@ -1397,7 +1397,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
var manager = GetApplicationManager(new[] { controllerTypeInfo });
|
||||
|
||||
var modelProvider = new DefaultApplicationModelProvider(options);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
manager,
|
||||
|
|
@ -1413,7 +1413,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var options = Options.Create(new MvcOptions());
|
||||
|
||||
var manager = GetApplicationManager(controllerTypeInfos);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
manager,
|
||||
|
|
@ -1432,7 +1432,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
var manager = GetApplicationManager(new[] { controllerTypeInfo });
|
||||
|
||||
var modelProvider = new DefaultApplicationModelProvider(options);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
manager,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Xunit;
|
||||
|
|
@ -74,6 +75,49 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_ReadsBindingSourceForPropertiesFromModelMetadata()
|
||||
{
|
||||
// Arrange
|
||||
var detailsProvider = new BindingSourceMetadataProvider(typeof(string), BindingSource.Services);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(new[] { detailsProvider });
|
||||
var typeInfo = typeof(ModelBinderController).GetTypeInfo();
|
||||
var provider = new TestApplicationModelProvider(Options.Create(new MvcOptions()), modelMetadataProvider);
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeInfo });
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
// Assert
|
||||
var controllerModel = Assert.Single(context.Result.Controllers);
|
||||
Assert.Collection(
|
||||
controllerModel.ControllerProperties.OrderBy(p => p.PropertyName),
|
||||
property =>
|
||||
{
|
||||
Assert.Equal(nameof(ModelBinderController.Bound), property.PropertyName);
|
||||
Assert.Equal(BindingSource.Query, property.BindingInfo.BindingSource);
|
||||
Assert.Same(controllerModel, property.Controller);
|
||||
|
||||
var attribute = Assert.Single(property.Attributes);
|
||||
Assert.IsType<FromQueryAttribute>(attribute);
|
||||
},
|
||||
property =>
|
||||
{
|
||||
Assert.Equal(nameof(ModelBinderController.FormFile), property.PropertyName);
|
||||
Assert.Equal(BindingSource.FormFile, property.BindingInfo.BindingSource);
|
||||
Assert.Same(controllerModel, property.Controller);
|
||||
|
||||
Assert.Empty(property.Attributes);
|
||||
},
|
||||
property =>
|
||||
{
|
||||
Assert.Equal(nameof(ModelBinderController.Unbound), property.PropertyName);
|
||||
Assert.Equal(BindingSource.Services, property.BindingInfo.BindingSource);
|
||||
Assert.Same(controllerModel, property.Controller);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_AddsBindingSources_ForActionParameters()
|
||||
{
|
||||
|
|
@ -88,7 +132,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
// Assert
|
||||
var controllerModel = Assert.Single(context.Result.Controllers);
|
||||
var action = Assert.Single(controllerModel.Actions);
|
||||
var action = Assert.Single(controllerModel.Actions, a => a.ActionMethod.Name == nameof(ModelBinderController.PostAction));
|
||||
Assert.Collection(
|
||||
action.Parameters,
|
||||
parameter =>
|
||||
|
|
@ -116,6 +160,107 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_AddsBindingSources_ForActionParameters_WithLegacyValidationBehavior()
|
||||
{
|
||||
// Arrange
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var options = Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = false });
|
||||
var builder = new TestApplicationModelProvider(options, modelMetadataProvider);
|
||||
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<FromQueryAttribute>(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_AddsBindingSources_ForActionParameters_ReadFromModelMetadata()
|
||||
{
|
||||
// Arrange
|
||||
var options = new MvcOptions { AllowValidatingTopLevelNodes = true };
|
||||
var detailsProvider = new BindingSourceMetadataProvider(typeof(Guid), BindingSource.Special);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(new[] { detailsProvider });
|
||||
|
||||
var provider = new TestApplicationModelProvider(Options.Create(options), modelMetadataProvider);
|
||||
var typeInfo = typeof(ModelBinderController).GetTypeInfo();
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeInfo });
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
// Assert
|
||||
var controllerModel = Assert.Single(context.Result.Controllers);
|
||||
var action = Assert.Single(controllerModel.Actions, a => a.ActionName == nameof(ModelBinderController.PostAction1));
|
||||
Assert.Collection(
|
||||
action.Parameters,
|
||||
parameter =>
|
||||
{
|
||||
Assert.Equal("guid", parameter.ParameterName);
|
||||
Assert.Equal(BindingSource.Special, parameter.BindingInfo.BindingSource);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_UsesBindingSourceSpecifiedOnParameter()
|
||||
{
|
||||
// Arrange
|
||||
var options = new MvcOptions();
|
||||
var detailsProvider = new BindingSourceMetadataProvider(typeof(Guid), BindingSource.Special);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(new[] { detailsProvider });
|
||||
|
||||
var provider = new TestApplicationModelProvider(Options.Create(options), modelMetadataProvider);
|
||||
var typeInfo = typeof(ModelBinderController).GetTypeInfo();
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeInfo });
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
// Assert
|
||||
var controllerModel = Assert.Single(context.Result.Controllers);
|
||||
var action = Assert.Single(controllerModel.Actions, a => a.ActionName == nameof(ModelBinderController.PostAction2));
|
||||
Assert.Collection(
|
||||
action.Parameters,
|
||||
parameter =>
|
||||
{
|
||||
Assert.Equal("fromQuery", parameter.ParameterName);
|
||||
Assert.Equal(BindingSource.Query, parameter.BindingInfo.BindingSource);
|
||||
});
|
||||
}
|
||||
|
||||
// This class has a filter attribute, but doesn't implement any filter interfaces,
|
||||
// so ControllerFilter is not present.
|
||||
[Fact]
|
||||
|
|
@ -1363,6 +1508,10 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
public IFormFile FormFile { get; set; }
|
||||
|
||||
public IActionResult PostAction([FromQuery] string fromQuery, IFormFileCollection formFileCollection, string unbound) => null;
|
||||
|
||||
public IActionResult PostAction1(Guid guid) => null;
|
||||
|
||||
public IActionResult PostAction2([FromQuery] Guid fromQuery) => null;
|
||||
}
|
||||
|
||||
public class SomeFiltersController : IAsyncActionFilter, IResultFilter
|
||||
|
|
@ -1404,13 +1553,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
private class TestApplicationModelProvider : DefaultApplicationModelProvider
|
||||
{
|
||||
public TestApplicationModelProvider()
|
||||
: this(Options.Create(new MvcOptions()))
|
||||
: this(Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }), TestModelMetadataProvider.CreateDefaultProvider())
|
||||
{
|
||||
}
|
||||
|
||||
public TestApplicationModelProvider(
|
||||
IOptions<MvcOptions> options)
|
||||
: base(options)
|
||||
IOptions<MvcOptions> options,
|
||||
IModelMetadataProvider modelMetadataProvider)
|
||||
: base(options, modelMetadataProvider)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Cors.Infrastructure;
|
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
|
|
@ -23,10 +24,7 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new [] { typeof(CorsController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = GetProviderContext(typeof(CorsController));
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -45,10 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(DisableCorsController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = GetProviderContext(typeof(DisableCorsController));
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -67,10 +62,7 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(CustomCorsFilterController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = GetProviderContext(typeof(CustomCorsFilterController));
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -88,10 +80,7 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(EnableCorsController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = GetProviderContext(typeof(EnableCorsController));
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -110,10 +99,7 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(DisableCorsActionController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = GetProviderContext(typeof(DisableCorsActionController));
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -132,10 +118,7 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(CustomCorsFilterOnActionController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = GetProviderContext(typeof(CustomCorsFilterOnActionController));
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -153,12 +136,10 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
var context = GetProviderContext(typeof(RegularController));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(RegularController).GetTypeInfo() });
|
||||
context.Result.Filters.Add(
|
||||
new CorsAuthorizationFilter(Mock.Of<ICorsService>(), Mock.Of<ICorsPolicyProvider>(), Mock.Of<ILoggerFactory>()));
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -176,11 +157,8 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(RegularController).GetTypeInfo() });
|
||||
var context = GetProviderContext(typeof(RegularController));
|
||||
context.Result.Filters.Add(new DisableCorsAuthorizationFilter());
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -198,11 +176,8 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(RegularController).GetTypeInfo() });
|
||||
var context = GetProviderContext(typeof(RegularController));
|
||||
context.Result.Filters.Add(new CustomCorsFilterAttribute());
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -220,10 +195,7 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
{
|
||||
// Arrange
|
||||
var corsProvider = new CorsApplicationModelProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(RegularController).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
var context = GetProviderContext(typeof(RegularController));
|
||||
|
||||
// Act
|
||||
corsProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -236,6 +208,17 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
|||
Assert.IsNotType<CorsHttpMethodActionConstraint>(constraint);
|
||||
}
|
||||
|
||||
private static ApplicationModelProviderContext GetProviderContext(Type controllerType)
|
||||
{
|
||||
var context = new ApplicationModelProviderContext(new[] { controllerType.GetTypeInfo() });
|
||||
var provider = new DefaultApplicationModelProvider(
|
||||
Options.Create(new MvcOptions()),
|
||||
TestModelMetadataProvider.CreateDefaultProvider());
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
private class EnableCorsController
|
||||
{
|
||||
[EnableCors("policy")]
|
||||
|
|
|
|||
|
|
@ -88,7 +88,14 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ActionsWithApiBehavior_InferFromBodyParameters()
|
||||
public Task ActionsWithApiBehavior_InferFromBodyParameters()
|
||||
=> ActionsWithApiBehaviorInferFromBodyParameters("ActionWithInferredFromBodyParameter");
|
||||
|
||||
[Fact]
|
||||
public Task ActionsWithApiBehavior_InferFromBodyParameters_DoNotConsiderCancellationTokenSourceParameter()
|
||||
=> ActionsWithApiBehaviorInferFromBodyParameters("ActionWithInferredFromBodyParameterAndCancellationToken");
|
||||
|
||||
private async Task ActionsWithApiBehaviorInferFromBodyParameters(string action)
|
||||
{
|
||||
// Arrange
|
||||
var input = new Contact
|
||||
|
|
@ -98,7 +105,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
};
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsJsonAsync("/contact/ActionWithInferredFromBodyParameter", input);
|
||||
var response = await Client.PostAsJsonAsync($"/contact/{action}", input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@ using Microsoft.AspNetCore.Mvc.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
||||
|
|
@ -31,13 +32,9 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
public async Task AuthorizeFilter_CalledTwiceWithNonDefaultProvider()
|
||||
{
|
||||
// Arrange
|
||||
var applicationModelProviderContext = new ApplicationModelProviderContext(
|
||||
new[] { typeof(AuthorizeController).GetTypeInfo() });
|
||||
var applicationModelProviderContext = GetProviderContext(typeof(AuthorizeController));
|
||||
|
||||
var policyProvider = new TestAuthorizationPolicyProvider();
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
|
||||
defaultProvider.OnProvidersExecuting(applicationModelProviderContext);
|
||||
|
||||
var controller = Assert.Single(applicationModelProviderContext.Result.Controllers);
|
||||
var action = Assert.Single(controller.Actions);
|
||||
|
|
@ -64,6 +61,17 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
return httpContext;
|
||||
}
|
||||
|
||||
private static ApplicationModelProviderContext GetProviderContext(Type controllerType)
|
||||
{
|
||||
var context = new ApplicationModelProviderContext(new[] { controllerType.GetTypeInfo() });
|
||||
var provider = new DefaultApplicationModelProvider(
|
||||
Options.Create(new MvcOptions()),
|
||||
TestModelMetadataProvider.CreateDefaultProvider());
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
private static IServiceProvider GetServices()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -160,7 +161,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
|
||||
private static PageApplicationModelProviderContext GetApplicationProviderContext(TypeInfo typeInfo)
|
||||
{
|
||||
var defaultProvider = new DefaultPageApplicationModelProvider();
|
||||
var defaultProvider = new DefaultPageApplicationModelProvider(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }));
|
||||
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
return context;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.Filters;
|
|||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||
|
|
@ -21,7 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_ThrowsIfPageDoesNotDeriveFromValidBaseType()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(InvalidPageWithWrongBaseClass).GetTypeInfo();
|
||||
var descriptor = new PageActionDescriptor();
|
||||
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
|
||||
|
|
@ -62,7 +63,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_ThrowsIfModelPropertyDoesNotExistOnPage()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithoutModelProperty).GetTypeInfo();
|
||||
var descriptor = new PageActionDescriptor();
|
||||
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
|
||||
|
|
@ -85,7 +86,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_ThrowsIfModelPropertyIsNotPublic()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithNonVisibleModel).GetTypeInfo();
|
||||
var descriptor = new PageActionDescriptor();
|
||||
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
|
||||
|
|
@ -110,7 +111,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_ThrowsIfModelPropertyIsStatic()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithStaticModel).GetTypeInfo();
|
||||
var descriptor = new PageActionDescriptor();
|
||||
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
|
||||
|
|
@ -135,7 +136,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_DiscoversPropertiesFromPage_IfModelTypeDoesNotHaveAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithModelWithoutPageModelAttribute).GetTypeInfo();
|
||||
var descriptor = new PageActionDescriptor();
|
||||
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
|
||||
|
|
@ -189,7 +190,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_DiscoversPropertiesFromPageModel_IfModelHasAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithModelWithPageModelAttribute).GetTypeInfo();
|
||||
var modelType = typeof(ModelWithPageModelAttribute);
|
||||
var descriptor = new PageActionDescriptor();
|
||||
|
|
@ -233,7 +234,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_DiscoversProperties_FromAllSubTypesThatDeclaresBindProperty()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(BindPropertyAttributeOnBaseModelPage).GetTypeInfo();
|
||||
var descriptor = new PageActionDescriptor();
|
||||
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
|
||||
|
|
@ -287,7 +288,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_DiscoversHandlersFromPage()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithModelWithoutHandlers).GetTypeInfo();
|
||||
var descriptor = new PageActionDescriptor();
|
||||
var context = new PageApplicationModelProviderContext(descriptor, typeInfo);
|
||||
|
|
@ -329,7 +330,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_DiscoversPropertiesFromModel()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithModel).GetTypeInfo();
|
||||
var modelType = typeof(TestPageModel);
|
||||
var descriptor = new PageActionDescriptor();
|
||||
|
|
@ -363,7 +364,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_DiscoversBindingInfoFromHandler()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithBindPropertyModel).GetTypeInfo();
|
||||
var modelType = typeof(ModelWithBindProperty);
|
||||
var descriptor = new PageActionDescriptor();
|
||||
|
|
@ -410,7 +411,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_DiscoversHandlersFromModel()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithModel).GetTypeInfo();
|
||||
var modelType = typeof(TestPageModel);
|
||||
var descriptor = new PageActionDescriptor();
|
||||
|
|
@ -438,7 +439,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_EmptyPage()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(EmptyPage).GetTypeInfo();
|
||||
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
|
||||
|
||||
|
|
@ -459,7 +460,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_EmptyPageModel()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(EmptyPageWithPageModel).GetTypeInfo();
|
||||
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
|
||||
|
||||
|
|
@ -528,7 +529,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void CreateDescriptor_FindsHandlerMethod_OnModel()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithHandlerThatGetsIgnored).GetTypeInfo();
|
||||
var modelType = typeof(ModelWithHandler);
|
||||
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
|
||||
|
|
@ -575,7 +576,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void OnProvidersExecuting_FindsHandlerMethodOnPage_WhenModelIsNotAnnotatedWithPageModelAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithHandler).GetTypeInfo();
|
||||
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
|
||||
|
||||
|
|
@ -626,7 +627,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateHandlerMethods_DiscoversHandlersFromBaseType()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(InheritsMethods).GetTypeInfo();
|
||||
var baseType = typeof(TestSetPageModel);
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
|
@ -677,7 +678,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateHandlerMethods_IgnoresNonPublicMethods()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(ProtectedModel).GetTypeInfo();
|
||||
var baseType = typeof(TestSetPageModel);
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
|
@ -705,7 +706,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateHandlerMethods_IgnoreGenericTypeParameters()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(GenericClassModel).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
||||
|
|
@ -728,7 +729,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateHandlerMethods_IgnoresStaticMethods()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageModelWithStaticHandler).GetTypeInfo();
|
||||
var expected = typeInfo.GetMethod(nameof(PageModelWithStaticHandler.OnGet), BindingFlags.Public | BindingFlags.Instance);
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
|
@ -758,7 +759,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateHandlerMethods_IgnoresAbstractMethods()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageModelWithAbstractMethod).GetTypeInfo();
|
||||
var expected = typeInfo.GetMethod(nameof(PageModelWithAbstractMethod.OnGet), BindingFlags.Public | BindingFlags.Instance);
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
|
@ -786,7 +787,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateHandlerMethods_IgnoresMethodWithNonHandlerAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageWithNonHandlerMethod).GetTypeInfo();
|
||||
var expected = typeInfo.GetMethod(nameof(PageWithNonHandlerMethod.OnGet), BindingFlags.Public | BindingFlags.Instance);
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
|
@ -817,7 +818,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void CreateHandlerModel_ParsesMethod()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(PageModelWithHandlerNames).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
||||
|
|
@ -851,7 +852,42 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void CreateHandlerMethods_AddsParameterDescriptors()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateHandlerMethods_WithLegacyValidationBehavior_AddsParameterDescriptors()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = false }));
|
||||
var typeInfo = typeof(PageWithHandlerParameters).GetTypeInfo();
|
||||
var expected = typeInfo.GetMethod(nameof(PageWithHandlerParameters.OnPost));
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
|
@ -895,7 +931,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateHandlerProperties_UsesPropertyHelpers_ToFindProperties()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(HidesAProperty).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
||||
|
|
@ -928,7 +964,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateHandlerProperties_SupportsGet_OnProperty()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(ModelSupportsGetOnProperty).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]);
|
||||
|
||||
|
|
@ -1039,7 +1075,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateFilters_AddsIFilterMetadataAttributesToModel()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(FilterModel).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, typeInfo.GetCustomAttributes(inherit: true));
|
||||
|
||||
|
|
@ -1063,7 +1099,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateFilters_AddsPageHandlerPageFilter_IfPageImplementsIAsyncPageFilter()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(ModelImplementingAsyncPageFilter).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, typeInfo.GetCustomAttributes(inherit: true));
|
||||
|
||||
|
|
@ -1093,7 +1129,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateFilters_AddsPageHandlerPageFilter_IfPageImplementsIPageFilter()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(ModelImplementingPageFilter).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, typeInfo.GetCustomAttributes(inherit: true));
|
||||
|
||||
|
|
@ -1128,7 +1164,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
public void PopulateFilters_AddsPageHandlerPageFilter_ForModelDerivingFromTypeImplementingPageFilter()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider();
|
||||
var provider = CreateProvider();
|
||||
var typeInfo = typeof(DerivedFromPageModel).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, typeInfo.GetCustomAttributes(inherit: true));
|
||||
|
||||
|
|
@ -1144,5 +1180,12 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
|
||||
[ServiceFilter(typeof(IServiceProvider))]
|
||||
private class DerivedFromPageModel : PageModel { }
|
||||
|
||||
private static DefaultPageApplicationModelProvider CreateProvider()
|
||||
{
|
||||
return new DefaultPageApplicationModelProvider(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Reflection;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
|
|
@ -136,7 +137,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
|
||||
private static PageApplicationModelProviderContext GetApplicationProviderContext(TypeInfo typeInfo)
|
||||
{
|
||||
var defaultProvider = new DefaultPageApplicationModelProvider();
|
||||
var defaultProvider = new DefaultPageApplicationModelProvider(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
Options.Create(new MvcOptions()));
|
||||
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
return context;
|
||||
|
|
|
|||
|
|
@ -183,6 +183,12 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
Assert.Equal(BindingSource.FormFile, formCollectionParameter.BindingSource);
|
||||
},
|
||||
provider =>
|
||||
{
|
||||
var formFileParameter = Assert.IsType<BindingSourceMetadataProvider>(provider);
|
||||
Assert.Equal(typeof(IFormFileCollection), formFileParameter.Type);
|
||||
Assert.Equal(BindingSource.FormFile, formFileParameter.BindingSource);
|
||||
},
|
||||
provider =>
|
||||
{
|
||||
var excludeFilter = Assert.IsType<SuppressChildValidationMetadataProvider>(provider);
|
||||
Assert.Equal(typeof(Type), excludeFilter.Type);
|
||||
|
|
@ -208,6 +214,11 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
Assert.Equal(typeof(IFormCollection), excludeFilter.Type);
|
||||
},
|
||||
provider =>
|
||||
{
|
||||
var excludeFilter = Assert.IsType<SuppressChildValidationMetadataProvider>(provider);
|
||||
Assert.Equal(typeof(IFormFileCollection), excludeFilter.Type);
|
||||
},
|
||||
provider =>
|
||||
{
|
||||
var excludeFilter = Assert.IsType<SuppressChildValidationMetadataProvider>(provider);
|
||||
Assert.Equal(typeof(Stream), excludeFilter.Type);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
// Creates a provider with all the defaults - includes data annotations
|
||||
public static ModelMetadataProvider CreateDefaultProvider(IStringLocalizerFactory stringLocalizerFactory = null)
|
||||
{
|
||||
var detailsProviders = new IMetadataDetailsProvider[]
|
||||
var detailsProviders = new List<IMetadataDetailsProvider>
|
||||
{
|
||||
new DefaultBindingMetadataProvider(),
|
||||
new DefaultValidationMetadataProvider(),
|
||||
|
|
@ -29,6 +29,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
new DataMemberRequiredBindingMetadataProvider(),
|
||||
};
|
||||
|
||||
MvcCoreMvcOptionsSetup.ConfigureAdditionalModelMetadataDetailsProvider(detailsProviders);
|
||||
|
||||
var compositeDetailsProvider = new DefaultCompositeMetadataDetailsProvider(detailsProviders);
|
||||
return new DefaultModelMetadataProvider(compositeDetailsProvider, Options.Create(new MvcOptions()));
|
||||
}
|
||||
|
|
@ -45,6 +47,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
new DataMemberRequiredBindingMetadataProvider(),
|
||||
};
|
||||
|
||||
MvcCoreMvcOptionsSetup.ConfigureAdditionalModelMetadataDetailsProvider(detailsProviders);
|
||||
|
||||
detailsProviders.AddRange(providers);
|
||||
|
||||
var compositeDetailsProvider = new DefaultCompositeMetadataDetailsProvider(detailsProviders);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -20,7 +21,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
var type = typeof(TestController_NoTempDataProperties);
|
||||
var options = Options.Create(new MvcViewOptions());
|
||||
var provider = new TempDataApplicationModelProvider(options);
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(
|
||||
Options.Create(new MvcOptions()),
|
||||
TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { type.GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -41,7 +44,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
var options = Options.Create(new MvcViewOptions());
|
||||
var provider = new TempDataApplicationModelProvider(options);
|
||||
var expected = $"The '{type.FullName}.Test' property with TempDataAttribute is invalid. A property using TempDataAttribute must have a public getter and setter.";
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(
|
||||
Options.Create(new MvcOptions()),
|
||||
TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { type.GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -58,7 +63,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
var type = typeof(TestController_NullableNonPrimitiveTempDataProperty);
|
||||
var options = Options.Create(new MvcViewOptions());
|
||||
var provider = new TempDataApplicationModelProvider(options);
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(
|
||||
Options.Create(new MvcOptions()),
|
||||
TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { type.GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -78,7 +85,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
var expected = typeof(TestController_OneTempDataProperty).GetProperty(nameof(TestController_OneTempDataProperty.Test2));
|
||||
var options = Options.Create(new MvcViewOptions());
|
||||
var provider = new TempDataApplicationModelProvider(options);
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(
|
||||
Options.Create(new MvcOptions()),
|
||||
TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(TestController_OneTempDataProperty).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
|
@ -102,7 +111,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
var expected = typeof(TestController_OneTempDataProperty).GetProperty(nameof(TestController_OneTempDataProperty.Test2));
|
||||
var options = Options.Create(new MvcViewOptions { SuppressTempDataAttributePrefix = true });
|
||||
var provider = new TempDataApplicationModelProvider(options);
|
||||
var defaultProvider = new DefaultApplicationModelProvider(Options.Create(new MvcOptions()));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(
|
||||
Options.Create(new MvcOptions()),
|
||||
TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(TestController_OneTempDataProperty).GetTypeInfo() });
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
|
|
|||
|
|
@ -379,22 +379,18 @@ namespace System.Web.Http
|
|||
var setup = new WebApiCompatShimOptionsSetup();
|
||||
setup.Configure(options);
|
||||
|
||||
var optionsAccessor = new Mock<IOptions<MvcOptions>>();
|
||||
optionsAccessor
|
||||
.SetupGet(o => o.Value)
|
||||
.Returns(options);
|
||||
|
||||
var authorizationOptionsAccessor = new Mock<IOptions<AuthorizationOptions>>();
|
||||
authorizationOptionsAccessor
|
||||
.SetupGet(o => o.Value)
|
||||
.Returns(new AuthorizationOptions());
|
||||
|
||||
var modelProvider = new DefaultApplicationModelProvider(optionsAccessor.Object);
|
||||
var optionsAccessor = Options.Create(options);
|
||||
var modelProvider = new DefaultApplicationModelProvider(optionsAccessor, TestModelMetadataProvider.CreateDefaultProvider());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
manager,
|
||||
new[] { modelProvider },
|
||||
optionsAccessor.Object);
|
||||
optionsAccessor);
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BasicWebSite.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
|
@ -51,6 +52,10 @@ namespace BasicWebSite
|
|||
[HttpPost("ActionWithInferredFromBodyParameter")]
|
||||
public ActionResult<Contact> ActionWithInferredFromBodyParameter(Contact contact) => contact;
|
||||
|
||||
[HttpPost(nameof(ActionWithInferredFromBodyParameterAndCancellationToken))]
|
||||
public ActionResult<Contact> ActionWithInferredFromBodyParameterAndCancellationToken(Contact contact, CancellationToken cts)
|
||||
=> contact;
|
||||
|
||||
[HttpPost("ActionWithInferredRouteAndQueryParameters/{name}/{id}")]
|
||||
public ActionResult<Contact> ActionWithInferredRouteAndQueryParameter(int id, string name, string email)
|
||||
{
|
||||
|
|
@ -68,4 +73,4 @@ namespace BasicWebSite
|
|||
return contact;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue