зеркало из https://github.com/aspnet/Mvc.git
Simplify BindAttribute - rename PredicateProvider
This change renames IPropertyBindingPredicateProvider to IPropertyFilterProvider. The changes here are mostly renames of parameters/variables from predicate -> propertyFilter. I did a find+replace and left the term 'predicate' in some of the docs because it refers to a predicate in the abstract sense. This change also simplifies BindAttribute and removes support for type activation.
This commit is contained in:
Родитель
1bd66ffda0
Коммит
144766f2e3
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
BindingSource = other.BindingSource;
|
||||
BinderModelName = other.BinderModelName;
|
||||
BinderType = other.BinderType;
|
||||
PropertyBindingPredicateProvider = other.PropertyBindingPredicateProvider;
|
||||
PropertyFilterProvider = other.PropertyFilterProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -52,9 +52,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
public Type BinderType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ModelBinding.IPropertyBindingPredicateProvider"/>.
|
||||
/// Gets or sets the <see cref="ModelBinding.IPropertyFilterProvider"/>.
|
||||
/// </summary>
|
||||
public IPropertyBindingPredicateProvider PropertyBindingPredicateProvider { get; set; }
|
||||
public IPropertyFilterProvider PropertyFilterProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of <see cref="BindingInfo"/> from the given <paramref name="attributes"/>.
|
||||
|
@ -100,46 +100,50 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
}
|
||||
|
||||
// PropertyBindingPredicateProvider
|
||||
var predicateProviders = attributes.OfType<IPropertyBindingPredicateProvider>().ToArray();
|
||||
if (predicateProviders.Length > 0)
|
||||
// PropertyFilterProvider
|
||||
var propertyFilterProviders = attributes.OfType<IPropertyFilterProvider>().ToArray();
|
||||
if (propertyFilterProviders.Length == 1)
|
||||
{
|
||||
isBindingInfoPresent = true;
|
||||
bindingInfo.PropertyBindingPredicateProvider = new CompositePredicateProvider(
|
||||
predicateProviders);
|
||||
bindingInfo.PropertyFilterProvider = propertyFilterProviders[0];
|
||||
}
|
||||
else if (propertyFilterProviders.Length > 1)
|
||||
{
|
||||
isBindingInfoPresent = true;
|
||||
bindingInfo.PropertyFilterProvider = new CompositePropertyFilterProvider(propertyFilterProviders);
|
||||
}
|
||||
|
||||
return isBindingInfoPresent ? bindingInfo : null;
|
||||
}
|
||||
|
||||
private class CompositePredicateProvider : IPropertyBindingPredicateProvider
|
||||
private class CompositePropertyFilterProvider : IPropertyFilterProvider
|
||||
{
|
||||
private readonly IEnumerable<IPropertyBindingPredicateProvider> _providers;
|
||||
private readonly IEnumerable<IPropertyFilterProvider> _providers;
|
||||
|
||||
public CompositePredicateProvider(IEnumerable<IPropertyBindingPredicateProvider> providers)
|
||||
public CompositePropertyFilterProvider(IEnumerable<IPropertyFilterProvider> providers)
|
||||
{
|
||||
_providers = providers;
|
||||
}
|
||||
|
||||
public Func<ModelBindingContext, string, bool> PropertyFilter
|
||||
public Func<ModelMetadata, bool> PropertyFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
return CreatePredicate();
|
||||
return CreatePropertyFilter();
|
||||
}
|
||||
}
|
||||
|
||||
private Func<ModelBindingContext, string, bool> CreatePredicate()
|
||||
private Func<ModelMetadata, bool> CreatePropertyFilter()
|
||||
{
|
||||
var predicates = _providers
|
||||
var propertyFilters = _providers
|
||||
.Select(p => p.PropertyFilter)
|
||||
.Where(p => p != null);
|
||||
|
||||
return (context, propertyName) =>
|
||||
return (m) =>
|
||||
{
|
||||
foreach (var predicate in predicates)
|
||||
foreach (var propertyFilter in propertyFilters)
|
||||
{
|
||||
if (!predicate(context, propertyName))
|
||||
if (!propertyFilter(m))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
/// <summary>
|
||||
/// Provides a predicate which can determines which model properties should be bound by model binding.
|
||||
/// </summary>
|
||||
public interface IPropertyBindingPredicateProvider
|
||||
public interface IPropertyFilterProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a predicate which can determines which model properties should be bound by model binding.
|
||||
/// </summary>
|
||||
Func<ModelBindingContext, string, bool> PropertyFilter { get; }
|
||||
Func<ModelMetadata, bool> PropertyFilter { get; }
|
||||
}
|
||||
}
|
|
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
/// Gets or sets a predicate which will be evaluated for each property to determine if the property
|
||||
/// is eligible for model binding.
|
||||
/// </summary>
|
||||
public abstract Func<ModelBindingContext, string, bool> PropertyFilter { get; set; }
|
||||
public abstract Func<ModelMetadata, bool> PropertyFilter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ValidationStateDictionary"/>. Used for tracking validation state to
|
||||
|
|
|
@ -269,10 +269,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
public abstract string NullDisplayText { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IPropertyBindingPredicateProvider"/>, which can determine which properties
|
||||
/// Gets the <see cref="IPropertyFilterProvider"/>, which can determine which properties
|
||||
/// should be model bound.
|
||||
/// </summary>
|
||||
public abstract IPropertyBindingPredicateProvider PropertyBindingPredicateProvider { get; }
|
||||
public abstract IPropertyFilterProvider PropertyFilterProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the property should be displayed in read-only views.
|
||||
|
|
|
@ -7,9 +7,7 @@ using System.Linq;
|
|||
#if NETSTANDARD1_5
|
||||
using System.Reflection;
|
||||
#endif
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
|
@ -17,14 +15,11 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// This attribute can be used on action parameters and types, to indicate model level metadata.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
|
||||
public class BindAttribute : Attribute, IModelNameProvider, IPropertyBindingPredicateProvider
|
||||
public class BindAttribute : Attribute, IModelNameProvider, IPropertyFilterProvider
|
||||
{
|
||||
private static readonly Func<ModelBindingContext, string, bool> _defaultFilter =
|
||||
(context, propertyName) => true;
|
||||
private static readonly Func<ModelMetadata, bool> _default = (m) => true;
|
||||
|
||||
private ObjectFactory _factory;
|
||||
|
||||
private Func<ModelBindingContext, string, bool> _predicateFromInclude;
|
||||
private Func<ModelMetadata, bool> _propertyFilter;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instace of <see cref="BindAttribute"/>.
|
||||
|
@ -41,33 +36,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
Include = items.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="BindAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="predicateProviderType">The type which implements
|
||||
/// <see cref="IPropertyBindingPredicateProvider"/>.
|
||||
/// </param>
|
||||
public BindAttribute(Type predicateProviderType)
|
||||
{
|
||||
if (predicateProviderType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(predicateProviderType));
|
||||
}
|
||||
|
||||
if (!typeof(IPropertyBindingPredicateProvider).IsAssignableFrom(predicateProviderType))
|
||||
{
|
||||
var message = Resources.FormatPropertyBindingPredicateProvider_WrongType(
|
||||
predicateProviderType.FullName,
|
||||
typeof(IPropertyBindingPredicateProvider).FullName);
|
||||
throw new ArgumentException(message, nameof(predicateProviderType));
|
||||
}
|
||||
|
||||
PredicateProviderType = predicateProviderType;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type PredicateProviderType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the names of properties to include in model binding.
|
||||
/// </summary>
|
||||
|
@ -91,64 +59,26 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Func<ModelBindingContext, string, bool> PropertyFilter
|
||||
public Func<ModelMetadata, bool> PropertyFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PredicateProviderType != null)
|
||||
if (Include != null && Include.Length > 0)
|
||||
{
|
||||
var factory = GetFactory();
|
||||
return CreatePredicateFromProviderType(factory);
|
||||
}
|
||||
else if (Include != null && Include.Length > 0)
|
||||
{
|
||||
if (_predicateFromInclude == null)
|
||||
if (_propertyFilter == null)
|
||||
{
|
||||
_predicateFromInclude =
|
||||
(context, propertyName) => Include.Contains(propertyName, StringComparer.Ordinal);
|
||||
_propertyFilter = (m) => Include.Contains(m.PropertyName, StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
return _predicateFromInclude;
|
||||
return _propertyFilter;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _defaultFilter;
|
||||
return _default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ObjectFactory GetFactory()
|
||||
{
|
||||
if (_factory == null)
|
||||
{
|
||||
_factory = ActivatorUtilities.CreateFactory(PredicateProviderType, Type.EmptyTypes);
|
||||
}
|
||||
return _factory;
|
||||
}
|
||||
|
||||
private static Func<ModelBindingContext, string, bool> CreatePredicateFromProviderType(
|
||||
ObjectFactory factory)
|
||||
{
|
||||
// Holding state to avoid execessive creation of the provider.
|
||||
var initialized = false;
|
||||
Func<ModelBindingContext, string, bool> predicate = null;
|
||||
|
||||
return (ModelBindingContext context, string propertyName) =>
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
var services = context.OperationBindingContext.HttpContext.RequestServices;
|
||||
|
||||
var provider = (IPropertyBindingPredicateProvider)factory(services, arguments: null);
|
||||
|
||||
initialized = true;
|
||||
predicate = provider.PropertyFilter ?? _defaultFilter;
|
||||
}
|
||||
|
||||
return predicate(context, propertyName);
|
||||
};
|
||||
}
|
||||
|
||||
private static IEnumerable<string> SplitString(string original)
|
||||
{
|
||||
if (string.IsNullOrEmpty(original))
|
||||
|
|
|
@ -1222,13 +1222,13 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="predicate">A predicate which can be used to filter properties at runtime.</param>
|
||||
/// <param name="propertyFilter">A predicate which can be used to filter properties at runtime.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
[NonAction]
|
||||
public Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
Func<ModelBindingContext, string, bool> predicate)
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
|
@ -1236,9 +1236,9 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (predicate == null)
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(predicate));
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
|
@ -1251,7 +1251,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
ControllerContext.InputFormatters,
|
||||
ObjectValidator,
|
||||
new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
|
||||
predicate);
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1311,14 +1311,14 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <param name="predicate">A predicate which can be used to filter properties at runtime.</param>
|
||||
/// <param name="propertyFilter">A predicate which can be used to filter properties at runtime.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
[NonAction]
|
||||
public Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
IValueProvider valueProvider,
|
||||
Func<ModelBindingContext, string, bool> predicate)
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
|
@ -1331,9 +1331,9 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
if (predicate == null)
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(predicate));
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
|
@ -1346,7 +1346,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
ControllerContext.InputFormatters,
|
||||
ObjectValidator,
|
||||
new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
|
||||
predicate);
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1396,7 +1396,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <param name="predicate">A predicate which can be used to filter properties at runtime.</param>
|
||||
/// <param name="propertyFilter">A predicate which can be used to filter properties at runtime.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
[NonAction]
|
||||
public Task<bool> TryUpdateModelAsync(
|
||||
|
@ -1404,7 +1404,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
Type modelType,
|
||||
string prefix,
|
||||
IValueProvider valueProvider,
|
||||
Func<ModelBindingContext, string, bool> predicate)
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
|
@ -1421,9 +1421,9 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
if (predicate == null)
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(predicate));
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
|
@ -1437,7 +1437,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
ControllerContext.InputFormatters,
|
||||
ObjectValidator,
|
||||
new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
|
||||
predicate);
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -69,20 +69,20 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
// Provide a unique instance based on one passed to the constructor.
|
||||
context.BindingMetadata.ModelBindingMessageProvider = new ModelBindingMessageProvider(_messageProvider);
|
||||
|
||||
// PropertyBindingPredicateProvider
|
||||
var predicateProviders = context.Attributes.OfType<IPropertyBindingPredicateProvider>().ToArray();
|
||||
if (predicateProviders.Length == 0)
|
||||
// PropertyFilterProvider
|
||||
var propertyFilterProviders = context.Attributes.OfType<IPropertyFilterProvider>().ToArray();
|
||||
if (propertyFilterProviders.Length == 0)
|
||||
{
|
||||
context.BindingMetadata.PropertyBindingPredicateProvider = null;
|
||||
context.BindingMetadata.PropertyFilterProvider = null;
|
||||
}
|
||||
else if (predicateProviders.Length == 1)
|
||||
else if (propertyFilterProviders.Length == 1)
|
||||
{
|
||||
context.BindingMetadata.PropertyBindingPredicateProvider = predicateProviders[0];
|
||||
context.BindingMetadata.PropertyFilterProvider = propertyFilterProviders[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
context.BindingMetadata.PropertyBindingPredicateProvider = new CompositePredicateProvider(
|
||||
predicateProviders);
|
||||
var composite = new CompositePropertyFilterProvider(propertyFilterProviders);
|
||||
context.BindingMetadata.PropertyFilterProvider = composite;
|
||||
}
|
||||
|
||||
if (context.Key.MetadataKind == ModelMetadataKind.Property)
|
||||
|
@ -107,34 +107,34 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
}
|
||||
}
|
||||
|
||||
private class CompositePredicateProvider : IPropertyBindingPredicateProvider
|
||||
private class CompositePropertyFilterProvider : IPropertyFilterProvider
|
||||
{
|
||||
private readonly IEnumerable<IPropertyBindingPredicateProvider> _providers;
|
||||
private readonly IEnumerable<IPropertyFilterProvider> _providers;
|
||||
|
||||
public CompositePredicateProvider(IEnumerable<IPropertyBindingPredicateProvider> providers)
|
||||
public CompositePropertyFilterProvider(IEnumerable<IPropertyFilterProvider> providers)
|
||||
{
|
||||
_providers = providers;
|
||||
}
|
||||
|
||||
public Func<ModelBindingContext, string, bool> PropertyFilter
|
||||
public Func<ModelMetadata, bool> PropertyFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
return CreatePredicate();
|
||||
return CreatePropertyFilter();
|
||||
}
|
||||
}
|
||||
|
||||
private Func<ModelBindingContext, string, bool> CreatePredicate()
|
||||
private Func<ModelMetadata, bool> CreatePropertyFilter()
|
||||
{
|
||||
var predicates = _providers
|
||||
var propertyFilters = _providers
|
||||
.Select(p => p.PropertyFilter)
|
||||
.Where(p => p != null);
|
||||
|
||||
return (context, propertyName) =>
|
||||
return (m) =>
|
||||
{
|
||||
foreach (var predicate in predicates)
|
||||
foreach (var propertyFilter in propertyFilters)
|
||||
{
|
||||
if (!predicate(context, propertyName))
|
||||
if (!propertyFilter(m))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -56,8 +56,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
var binderModelName = bindingInfo?.BinderModelName ?? metadata.BinderModelName;
|
||||
var propertyPredicateProvider =
|
||||
bindingInfo?.PropertyBindingPredicateProvider ?? metadata.PropertyBindingPredicateProvider;
|
||||
var propertyFilterProvider = bindingInfo?.PropertyFilterProvider ?? metadata.PropertyFilterProvider;
|
||||
|
||||
var valueProvider = operationBindingContext.ValueProvider;
|
||||
var bindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource;
|
||||
|
@ -70,7 +69,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{
|
||||
BinderModelName = binderModelName,
|
||||
BindingSource = bindingSource,
|
||||
PropertyFilter = propertyPredicateProvider?.PropertyFilter,
|
||||
PropertyFilter = propertyFilterProvider?.PropertyFilter,
|
||||
|
||||
// Because this is the top-level context, FieldName and ModelName should be the same.
|
||||
FieldName = binderModelName ?? modelName,
|
||||
|
@ -123,7 +122,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
FieldName = fieldName;
|
||||
BinderModelName = modelMetadata.BinderModelName;
|
||||
BindingSource = modelMetadata.BindingSource;
|
||||
PropertyFilter = modelMetadata.PropertyBindingPredicateProvider?.PropertyFilter;
|
||||
PropertyFilter = modelMetadata.PropertyFilterProvider?.PropertyFilter;
|
||||
|
||||
IsTopLevelObject = false;
|
||||
|
||||
|
@ -262,7 +261,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Func<ModelBindingContext, string, bool> PropertyFilter
|
||||
public override Func<ModelMetadata, bool> PropertyFilter
|
||||
{
|
||||
get { return _state.PropertyFilter; }
|
||||
set { _state.PropertyFilter = value; }
|
||||
|
@ -317,7 +316,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
public string ModelName;
|
||||
|
||||
public IValueProvider ValueProvider;
|
||||
public Func<ModelBindingContext, string, bool> PropertyFilter;
|
||||
public Func<ModelMetadata, bool> PropertyFilter;
|
||||
public ValidationStateDictionary ValidationState;
|
||||
public ModelStateDictionary ModelState;
|
||||
|
||||
|
|
|
@ -114,13 +114,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
/// <returns><c>true</c> if the model property can be bound, otherwise <c>false</c>.</returns>
|
||||
protected virtual bool CanBindProperty(ModelBindingContext bindingContext, ModelMetadata propertyMetadata)
|
||||
{
|
||||
var modelMetadataPredicate = bindingContext.ModelMetadata.PropertyBindingPredicateProvider?.PropertyFilter;
|
||||
if (modelMetadataPredicate?.Invoke(bindingContext, propertyMetadata.PropertyName) == false)
|
||||
var metadataProviderFilter = bindingContext.ModelMetadata.PropertyFilterProvider?.PropertyFilter;
|
||||
if (metadataProviderFilter?.Invoke(propertyMetadata) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bindingContext.PropertyFilter?.Invoke(bindingContext, propertyMetadata.PropertyName) == false)
|
||||
if (bindingContext.PropertyFilter?.Invoke(propertyMetadata) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -5,20 +5,18 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation for <see cref="IPropertyBindingPredicateProvider"/>.
|
||||
/// Default implementation for <see cref="IPropertyFilterProvider"/>.
|
||||
/// Provides a expression based way to provide include properties.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The target model Type.</typeparam>
|
||||
public class DefaultPropertyBindingPredicateProvider<TModel> : IPropertyBindingPredicateProvider
|
||||
public class DefaultPropertyFilterProvider<TModel> : IPropertyFilterProvider
|
||||
where TModel : class
|
||||
{
|
||||
private static readonly Func<ModelBindingContext, string, bool> _defaultFilter =
|
||||
(context, propertyName) => true;
|
||||
private static readonly Func<ModelMetadata, bool> _default = (m) => true;
|
||||
|
||||
/// <summary>
|
||||
/// The prefix which is used while generating the property filter.
|
||||
|
@ -44,24 +42,24 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Func<ModelBindingContext, string, bool> PropertyFilter
|
||||
public virtual Func<ModelMetadata, bool> PropertyFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PropertyIncludeExpressions == null)
|
||||
{
|
||||
return _defaultFilter;
|
||||
return _default;
|
||||
}
|
||||
|
||||
// We do not cache by default.
|
||||
return GetPredicateFromExpression(PropertyIncludeExpressions);
|
||||
return GetPropertyFilterFromExpression(PropertyIncludeExpressions);
|
||||
}
|
||||
}
|
||||
|
||||
private Func<ModelBindingContext, string, bool> GetPredicateFromExpression(
|
||||
private Func<ModelMetadata, bool> GetPropertyFilterFromExpression(
|
||||
IEnumerable<Expression<Func<TModel, object>>> includeExpressions)
|
||||
{
|
||||
var expression = ModelBindingHelper.GetIncludePredicateExpression(Prefix, includeExpressions.ToArray());
|
||||
var expression = ModelBindingHelper.GetPropertyFilterExpression(includeExpressions.ToArray());
|
||||
return expression.Compile();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,9 +74,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ModelBinding.IPropertyBindingPredicateProvider"/>.
|
||||
/// See <see cref="ModelMetadata.PropertyBindingPredicateProvider"/>.
|
||||
/// Gets or sets the <see cref="ModelBinding.IPropertyFilterProvider"/>.
|
||||
/// See <see cref="ModelMetadata.PropertyFilterProvider"/>.
|
||||
/// </summary>
|
||||
public IPropertyBindingPredicateProvider PropertyBindingPredicateProvider { get; set; }
|
||||
public IPropertyFilterProvider PropertyFilterProvider { get; set; }
|
||||
}
|
||||
}
|
|
@ -456,11 +456,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IPropertyBindingPredicateProvider PropertyBindingPredicateProvider
|
||||
public override IPropertyFilterProvider PropertyFilterProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
return BindingMetadata.PropertyBindingPredicateProvider;
|
||||
return BindingMetadata.PropertyFilterProvider;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
BinderModelName = metadata.BinderModelName,
|
||||
BinderType = metadata.BinderType,
|
||||
BindingSource = metadata.BindingSource,
|
||||
PropertyBindingPredicateProvider = metadata.PropertyBindingPredicateProvider,
|
||||
PropertyFilterProvider = metadata.PropertyFilterProvider,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
inputFormatters,
|
||||
objectModelValidator,
|
||||
validatorProvider,
|
||||
predicate: (context, propertyName) => true);
|
||||
propertyFilter: (m) => true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -198,8 +198,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
throw new ArgumentNullException(nameof(includeExpressions));
|
||||
}
|
||||
|
||||
var includeExpression = GetIncludePredicateExpression(prefix, includeExpressions);
|
||||
var predicate = includeExpression.Compile();
|
||||
var expression = GetPropertyFilterExpression(includeExpressions);
|
||||
var propertyFilter = expression.Compile();
|
||||
|
||||
return TryUpdateModelAsync(
|
||||
model,
|
||||
|
@ -211,7 +211,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
inputFormatters,
|
||||
objectModelValidator,
|
||||
validatorProvider,
|
||||
predicate: predicate);
|
||||
propertyFilter: propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -234,8 +234,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
/// bound values.</param>
|
||||
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/> used for executing validation
|
||||
/// on the model instance.</param>
|
||||
/// <param name="predicate">A predicate which can be used to
|
||||
/// filter properties(for inclusion/exclusion) at runtime.</param>
|
||||
/// <param name="propertyFilter">
|
||||
/// A predicate which can be used to filter properties(for inclusion/exclusion) at runtime.
|
||||
/// </param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
|
||||
public static Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
|
@ -247,7 +248,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
IList<IInputFormatter> inputFormatters,
|
||||
IObjectModelValidator objectModelValidator,
|
||||
IModelValidatorProvider validatorProvider,
|
||||
Func<ModelBindingContext, string, bool> predicate)
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
|
@ -295,9 +296,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
throw new ArgumentNullException(nameof(validatorProvider));
|
||||
}
|
||||
|
||||
if (predicate == null)
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(predicate));
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return TryUpdateModelAsync(
|
||||
|
@ -311,7 +312,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
inputFormatters,
|
||||
objectModelValidator,
|
||||
validatorProvider,
|
||||
predicate: predicate);
|
||||
propertyFilter: propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -409,7 +410,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
inputFormatters,
|
||||
objectModelValidator,
|
||||
validatorProvider,
|
||||
predicate: (context, propertyName) => true);
|
||||
propertyFilter: (m) => true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -432,21 +433,21 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
/// bound values.</param>
|
||||
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/> used for executing validation
|
||||
/// on the model instance.</param>
|
||||
/// <param name="predicate">A predicate which can be used to
|
||||
/// <param name="propertyFilter">A predicate which can be used to
|
||||
/// filter properties(for inclusion/exclusion) at runtime.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
|
||||
public static async Task<bool> TryUpdateModelAsync(
|
||||
object model,
|
||||
Type modelType,
|
||||
string prefix,
|
||||
ActionContext actionContext,
|
||||
IModelMetadataProvider metadataProvider,
|
||||
IModelBinderFactory modelBinderFactory,
|
||||
IValueProvider valueProvider,
|
||||
IList<IInputFormatter> inputFormatters,
|
||||
IObjectModelValidator objectModelValidator,
|
||||
IModelValidatorProvider validatorProvider,
|
||||
Func<ModelBindingContext, string, bool> predicate)
|
||||
object model,
|
||||
Type modelType,
|
||||
string prefix,
|
||||
ActionContext actionContext,
|
||||
IModelMetadataProvider metadataProvider,
|
||||
IModelBinderFactory modelBinderFactory,
|
||||
IValueProvider valueProvider,
|
||||
IList<IInputFormatter> inputFormatters,
|
||||
IObjectModelValidator objectModelValidator,
|
||||
IModelValidatorProvider validatorProvider,
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
|
@ -498,9 +499,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
throw new ArgumentNullException(nameof(validatorProvider));
|
||||
}
|
||||
|
||||
if (predicate == null)
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(predicate));
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
if (!modelType.IsAssignableFrom(model.GetType()))
|
||||
|
@ -529,7 +530,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
bindingInfo: null,
|
||||
modelName: prefix ?? string.Empty);
|
||||
modelBindingContext.Model = model;
|
||||
modelBindingContext.PropertyFilter = predicate;
|
||||
modelBindingContext.PropertyFilter = propertyFilter;
|
||||
|
||||
var factoryContext = new ModelBinderFactoryContext()
|
||||
{
|
||||
|
@ -539,7 +540,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
BinderModelName = modelMetadata.BinderModelName,
|
||||
BinderType = modelMetadata.BinderType,
|
||||
BindingSource = modelMetadata.BindingSource,
|
||||
PropertyBindingPredicateProvider = modelMetadata.PropertyBindingPredicateProvider,
|
||||
PropertyFilterProvider = modelMetadata.PropertyFilterProvider,
|
||||
},
|
||||
|
||||
// We're using the model metadata as the cache token here so that TryUpdateModelAsync calls
|
||||
|
@ -607,42 +608,36 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
/// Creates an expression for a predicate to limit the set of properties used in model binding.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The model type.</typeparam>
|
||||
/// <param name="prefix">The model prefix.</param>
|
||||
/// <param name="expressions">Expressions identifying the properties to allow for binding.</param>
|
||||
/// <returns>An expression which can be used with <see cref="IPropertyBindingPredicateProvider"/>.</returns>
|
||||
public static Expression<Func<ModelBindingContext, string, bool>> GetIncludePredicateExpression<TModel>(
|
||||
string prefix,
|
||||
/// <returns>An expression which can be used with <see cref="IPropertyFilterProvider"/>.</returns>
|
||||
public static Expression<Func<ModelMetadata, bool>> GetPropertyFilterExpression<TModel>(
|
||||
Expression<Func<TModel, object>>[] expressions)
|
||||
{
|
||||
if (expressions.Length == 0)
|
||||
{
|
||||
// If nothing is included explcitly, treat everything as included.
|
||||
return (context, propertyName) => true;
|
||||
// If nothing is included explicitly, treat everything as included.
|
||||
return (m) => true;
|
||||
}
|
||||
|
||||
var firstExpression = GetPredicateExpression(prefix, expressions[0]);
|
||||
var firstExpression = GetPredicateExpression(expressions[0]);
|
||||
var orWrapperExpression = firstExpression.Body;
|
||||
foreach (var expression in expressions.Skip(1))
|
||||
{
|
||||
var predicate = GetPredicateExpression(prefix, expression);
|
||||
orWrapperExpression = Expression.OrElse(orWrapperExpression,
|
||||
Expression.Invoke(predicate, firstExpression.Parameters));
|
||||
var predicate = GetPredicateExpression(expression);
|
||||
orWrapperExpression = Expression.OrElse(
|
||||
orWrapperExpression,
|
||||
Expression.Invoke(predicate, firstExpression.Parameters));
|
||||
}
|
||||
|
||||
return Expression.Lambda<Func<ModelBindingContext, string, bool>>(
|
||||
orWrapperExpression, firstExpression.Parameters);
|
||||
return Expression.Lambda<Func<ModelMetadata, bool>>(orWrapperExpression, firstExpression.Parameters);
|
||||
}
|
||||
|
||||
private static Expression<Func<ModelBindingContext, string, bool>> GetPredicateExpression<TModel>
|
||||
(string prefix, Expression<Func<TModel, object>> expression)
|
||||
private static Expression<Func<ModelMetadata, bool>> GetPredicateExpression<TModel>(
|
||||
Expression<Func<TModel, object>> expression)
|
||||
{
|
||||
var propertyName = GetPropertyName(expression.Body);
|
||||
var property = ModelNames.CreatePropertyModelName(prefix, propertyName);
|
||||
|
||||
return
|
||||
(context, modelPropertyName) =>
|
||||
property.Equals(ModelNames.CreatePropertyModelName(context.ModelName, modelPropertyName),
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
return (metadata) => string.Equals(metadata.PropertyName, propertyName, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -922,22 +922,6 @@ namespace Microsoft.AspNetCore.Mvc.Core
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("ModelBinding_MissingBindRequiredMember"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type '{0}' does not implement the interface '{1}'.
|
||||
/// </summary>
|
||||
internal static string PropertyBindingPredicateProvider_WrongType
|
||||
{
|
||||
get { return GetString("PropertyBindingPredicateProvider_WrongType"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type '{0}' does not implement the interface '{1}'.
|
||||
/// </summary>
|
||||
internal static string FormatPropertyBindingPredicateProvider_WrongType(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("PropertyBindingPredicateProvider_WrongType"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.
|
||||
/// </summary>
|
||||
|
@ -1159,7 +1143,7 @@ namespace Microsoft.AspNetCore.Mvc.Core
|
|||
/// </summary>
|
||||
internal static string FormatMustSpecifyAtLeastOneAuthenticationScheme()
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("MustSpecifyAtLeastOneAuthenticationScheme"));
|
||||
return GetString("MustSpecifyAtLeastOneAuthenticationScheme");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -297,9 +297,6 @@
|
|||
<data name="ModelBinding_MissingBindRequiredMember" xml:space="preserve">
|
||||
<value>A value for the '{0}' property was not provided.</value>
|
||||
</data>
|
||||
<data name="PropertyBindingPredicateProvider_WrongType" xml:space="preserve">
|
||||
<value>The type '{0}' does not implement the interface '{1}'.</value>
|
||||
</data>
|
||||
<data name="ValueProviderResult_NoConverterExists" xml:space="preserve">
|
||||
<value>The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.</value>
|
||||
</data>
|
||||
|
|
|
@ -536,7 +536,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
}
|
||||
|
||||
public override IPropertyBindingPredicateProvider PropertyBindingPredicateProvider
|
||||
public override IPropertyFilterProvider PropertyFilterProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
@ -10,34 +11,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{
|
||||
public class BindAttributeTest
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_Throws_IfTypeDoesNotImplement_IPropertyBindingPredicateProvider()
|
||||
{
|
||||
// Arrange
|
||||
var expected =
|
||||
"The type 'Microsoft.AspNetCore.Mvc.ModelBinding.BindAttributeTest+UnrelatedType' " +
|
||||
"does not implement the interface " +
|
||||
"'Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyBindingPredicateProvider'." +
|
||||
Environment.NewLine +
|
||||
"Parameter name: predicateProviderType";
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<ArgumentException>(() => new BindAttribute(typeof(UnrelatedType)));
|
||||
Assert.Equal(expected, exception.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(DerivedProvider))]
|
||||
[InlineData(typeof(BaseProvider))]
|
||||
public void Constructor_SetsThe_PropertyFilterProviderType_ForValidTypes(Type type)
|
||||
{
|
||||
// Arrange
|
||||
var attribute = new BindAttribute(type);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Equal(type, attribute.PredicateProviderType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("UserName", true)]
|
||||
[InlineData("Username", false)]
|
||||
|
@ -54,98 +27,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
|
||||
var context = new DefaultModelBindingContext();
|
||||
|
||||
// Act
|
||||
var predicate = bind.PropertyFilter;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(isIncluded, predicate(context, property));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("UserName", true)]
|
||||
[InlineData("Username", false)]
|
||||
[InlineData("Password", false)]
|
||||
public void BindAttribute_ProviderType(string property, bool isIncluded)
|
||||
{
|
||||
// Arrange
|
||||
var bind = new BindAttribute(typeof(TestProvider));
|
||||
|
||||
var context = new DefaultModelBindingContext();
|
||||
context.OperationBindingContext = new OperationBindingContext()
|
||||
{
|
||||
ActionContext = new ActionContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
},
|
||||
};
|
||||
var services = new Mock<IServiceProvider>();
|
||||
|
||||
context.OperationBindingContext.HttpContext.RequestServices = services.Object;
|
||||
var identity = ModelMetadataIdentity.ForProperty(typeof(int), property, typeof(string));
|
||||
context.ModelMetadata = new Mock<ModelMetadata>(identity).Object;
|
||||
|
||||
// Act
|
||||
var predicate = bind.PropertyFilter;
|
||||
var propertyFilter = bind.PropertyFilter;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(isIncluded, predicate(context, property));
|
||||
}
|
||||
|
||||
// Each time .PropertyFilter is called, a since instance of the provider should
|
||||
// be created and cached.
|
||||
[Fact]
|
||||
public void BindAttribute_ProviderType_Cached()
|
||||
{
|
||||
// Arrange
|
||||
var bind = new BindAttribute(typeof(TestProvider));
|
||||
|
||||
var context = new DefaultModelBindingContext();
|
||||
context.OperationBindingContext = new OperationBindingContext()
|
||||
{
|
||||
ActionContext = new ActionContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
},
|
||||
};
|
||||
|
||||
var services = new Mock<IServiceProvider>(MockBehavior.Strict);
|
||||
|
||||
context.OperationBindingContext.HttpContext.RequestServices = services.Object;
|
||||
|
||||
// Act
|
||||
var predicate = bind.PropertyFilter;
|
||||
|
||||
// Assert
|
||||
Assert.True(predicate(context, "UserName"));
|
||||
Assert.True(predicate(context, "UserName"));
|
||||
}
|
||||
|
||||
private class TestProvider : IPropertyBindingPredicateProvider
|
||||
{
|
||||
public Func<ModelBindingContext, string, bool> PropertyFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
return (context, property) => string.Equals(property, "UserName", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BaseProvider : IPropertyBindingPredicateProvider
|
||||
{
|
||||
public Func<ModelBindingContext, string, bool> PropertyFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DerivedProvider : BaseProvider
|
||||
{
|
||||
}
|
||||
|
||||
private class UnrelatedType
|
||||
{
|
||||
Assert.Equal(isIncluded, propertyFilter(context.ModelMetadata));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1151,8 +1151,8 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
|
||||
// Include and exclude should be null, resulting in property
|
||||
// being included.
|
||||
Assert.True(context.PropertyFilter(context, "Property1"));
|
||||
Assert.True(context.PropertyFilter(context, "Property2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property2"]));
|
||||
});
|
||||
|
||||
var controller = GetController(binder, valueProvider);
|
||||
|
@ -1179,8 +1179,8 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
|
||||
// Include and exclude should be null, resulting in property
|
||||
// being included.
|
||||
Assert.True(context.PropertyFilter(context, "Property1"));
|
||||
Assert.True(context.PropertyFilter(context, "Property2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property2"]));
|
||||
});
|
||||
|
||||
var controller = GetController(binder, valueProvider);
|
||||
|
@ -1206,8 +1206,8 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
|
||||
// Include and exclude should be null, resulting in property
|
||||
// being included.
|
||||
Assert.True(context.PropertyFilter(context, "Property1"));
|
||||
Assert.True(context.PropertyFilter(context, "Property2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property2"]));
|
||||
});
|
||||
|
||||
var controller = GetController(binder, valueProvider: null);
|
||||
|
@ -1221,64 +1221,65 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryUpdateModel_PredicateOverload_UsesPassedArguments()
|
||||
public async Task TryUpdateModel_PropertyFilterOverload_UsesPassedArguments()
|
||||
{
|
||||
// Arrange
|
||||
var modelName = "mymodel";
|
||||
|
||||
Func<ModelBindingContext, string, bool> includePredicate = (context, propertyName) =>
|
||||
string.Equals(propertyName, "include1", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(propertyName, "include2", StringComparison.OrdinalIgnoreCase);
|
||||
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
||||
string.Equals(m.PropertyName, "Include1", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(m.PropertyName, "Include2", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var valueProvider = Mock.Of<IValueProvider>();
|
||||
var binder = new StubModelBinder(context =>
|
||||
{
|
||||
Assert.Same(valueProvider, Assert.IsType<CompositeValueProvider>(context.ValueProvider)[0]);
|
||||
|
||||
Assert.True(context.PropertyFilter(context, "include1"));
|
||||
Assert.True(context.PropertyFilter(context, "include2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Include1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Include2"]));
|
||||
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude1"]));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude2"]));
|
||||
|
||||
Assert.False(context.PropertyFilter(context, "exclude1"));
|
||||
Assert.False(context.PropertyFilter(context, "exclude2"));
|
||||
});
|
||||
|
||||
var controller = GetController(binder, valueProvider);
|
||||
var model = new MyModel();
|
||||
|
||||
// Act
|
||||
await controller.TryUpdateModelAsync(model, modelName, includePredicate);
|
||||
await controller.TryUpdateModelAsync(model, modelName, propertyFilter);
|
||||
|
||||
// Assert
|
||||
Assert.NotEqual(0, binder.BindModelCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryUpdateModel_PredicateWithValueProviderOverload_UsesPassedArguments()
|
||||
public async Task TryUpdateModel_PropertyFilterWithValueProviderOverload_UsesPassedArguments()
|
||||
{
|
||||
// Arrange
|
||||
var modelName = "mymodel";
|
||||
|
||||
Func<ModelBindingContext, string, bool> includePredicate =
|
||||
(context, propertyName) => string.Equals(propertyName, "include1", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(propertyName, "include2", StringComparison.OrdinalIgnoreCase);
|
||||
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
||||
string.Equals(m.PropertyName, "Include1", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(m.PropertyName, "Include2", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var valueProvider = Mock.Of<IValueProvider>();
|
||||
var binder = new StubModelBinder(context =>
|
||||
{
|
||||
Assert.Same(valueProvider, context.ValueProvider);
|
||||
|
||||
Assert.True(context.PropertyFilter(context, "include1"));
|
||||
Assert.True(context.PropertyFilter(context, "include2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Include1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Include2"]));
|
||||
|
||||
Assert.False(context.PropertyFilter(context, "exclude1"));
|
||||
Assert.False(context.PropertyFilter(context, "exclude2"));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude1"]));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude2"]));
|
||||
});
|
||||
var controller = GetController(binder, valueProvider: null);
|
||||
|
||||
var model = new MyModel();
|
||||
|
||||
// Act
|
||||
await controller.TryUpdateModelAsync(model, modelName, valueProvider, includePredicate);
|
||||
await controller.TryUpdateModelAsync(model, modelName, valueProvider, propertyFilter);
|
||||
|
||||
// Assert
|
||||
Assert.NotEqual(0, binder.BindModelCount);
|
||||
|
@ -1298,14 +1299,14 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
var binder = new StubModelBinder(context =>
|
||||
{
|
||||
Assert.Same(
|
||||
valueProvider.Object,
|
||||
Assert.IsType<CompositeValueProvider>(context.ValueProvider)[0]);
|
||||
valueProvider.Object,
|
||||
Assert.IsType<CompositeValueProvider>(context.ValueProvider)[0]);
|
||||
|
||||
Assert.True(context.PropertyFilter(context, "Property1"));
|
||||
Assert.True(context.PropertyFilter(context, "Property2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property2"]));
|
||||
|
||||
Assert.False(context.PropertyFilter(context, "exclude1"));
|
||||
Assert.False(context.PropertyFilter(context, "exclude2"));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude1"]));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude2"]));
|
||||
});
|
||||
|
||||
|
||||
|
@ -1335,11 +1336,11 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
{
|
||||
Assert.Same(valueProvider.Object, context.ValueProvider);
|
||||
|
||||
Assert.True(context.PropertyFilter(context, "Property1"));
|
||||
Assert.True(context.PropertyFilter(context, "Property2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property2"]));
|
||||
|
||||
Assert.False(context.PropertyFilter(context, "exclude1"));
|
||||
Assert.False(context.PropertyFilter(context, "exclude2"));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude1"]));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude2"]));
|
||||
});
|
||||
|
||||
var controller = GetController(binder, valueProvider: null);
|
||||
|
@ -1353,14 +1354,14 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryUpdateModelNonGeneric_PredicateWithValueProviderOverload_UsesPassedArguments()
|
||||
public async Task TryUpdateModelNonGeneric_PropertyFilterWithValueProviderOverload_UsesPassedArguments()
|
||||
{
|
||||
// Arrange
|
||||
var modelName = "mymodel";
|
||||
|
||||
Func<ModelBindingContext, string, bool> includePredicate =
|
||||
(context, propertyName) => string.Equals(propertyName, "include1", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(propertyName, "include2", StringComparison.OrdinalIgnoreCase);
|
||||
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
||||
string.Equals(m.PropertyName, "Include1", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(m.PropertyName, "Include2", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var valueProvider = Mock.Of<IValueProvider>();
|
||||
|
||||
|
@ -1368,11 +1369,11 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
{
|
||||
Assert.Same(valueProvider, context.ValueProvider);
|
||||
|
||||
Assert.True(context.PropertyFilter(context, "include1"));
|
||||
Assert.True(context.PropertyFilter(context, "include2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Include1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Include2"]));
|
||||
|
||||
Assert.False(context.PropertyFilter(context, "exclude1"));
|
||||
Assert.False(context.PropertyFilter(context, "exclude2"));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude1"]));
|
||||
Assert.False(context.PropertyFilter(context.ModelMetadata.Properties["Exclude2"]));
|
||||
});
|
||||
|
||||
var controller = GetController(binder, valueProvider: null);
|
||||
|
@ -1380,7 +1381,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
var model = new MyModel();
|
||||
|
||||
// Act
|
||||
await controller.TryUpdateModelAsync(model, model.GetType(), modelName, valueProvider, includePredicate);
|
||||
await controller.TryUpdateModelAsync(model, model.GetType(), modelName, valueProvider, propertyFilter);
|
||||
|
||||
// Assert
|
||||
Assert.NotEqual(0, binder.BindModelCount);
|
||||
|
@ -1400,8 +1401,8 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
|
||||
// Include and exclude should be null, resulting in property
|
||||
// being included.
|
||||
Assert.True(context.PropertyFilter(context, "Property1"));
|
||||
Assert.True(context.PropertyFilter(context, "Property2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property2"]));
|
||||
});
|
||||
|
||||
var controller = GetController(binder, valueProvider);
|
||||
|
@ -1428,8 +1429,8 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
|
||||
// Include and exclude should be null, resulting in property
|
||||
// being included.
|
||||
Assert.True(context.PropertyFilter(context, "Property1"));
|
||||
Assert.True(context.PropertyFilter(context, "Property2"));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property1"]));
|
||||
Assert.True(context.PropertyFilter(context.ModelMetadata.Properties["Property2"]));
|
||||
});
|
||||
|
||||
var controller = GetController(binder, valueProvider);
|
||||
|
@ -1667,6 +1668,12 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
{
|
||||
public string Property1 { get; set; }
|
||||
public string Property2 { get; set; }
|
||||
|
||||
public string Include1 { get; set; }
|
||||
public string Include2 { get; set; }
|
||||
|
||||
public string Exclude1 { get; set; }
|
||||
public string Exclude2 { get; set; }
|
||||
}
|
||||
|
||||
private class MyDerivedModel : MyModel
|
||||
|
|
|
@ -488,39 +488,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(nameof(TypeWithExcludedPropertiesUsingBindAttribute.IncludedByDefault1), true)]
|
||||
[InlineData(nameof(TypeWithExcludedPropertiesUsingBindAttribute.IncludedByDefault2), true)]
|
||||
[InlineData(nameof(TypeWithExcludedPropertiesUsingBindAttribute.Excluded1), false)]
|
||||
[InlineData(nameof(TypeWithExcludedPropertiesUsingBindAttribute.Excluded2), false)]
|
||||
public void CanBindProperty_WithPredicate(string property, bool expected)
|
||||
{
|
||||
// Arrange
|
||||
var metadata = GetMetadataForProperty(typeof(TypeWithExcludedPropertiesUsingBindAttribute), property);
|
||||
var bindingContext = new DefaultModelBindingContext()
|
||||
{
|
||||
ModelMetadata = GetMetadataForType(typeof(TypeWithExcludedPropertiesUsingBindAttribute)),
|
||||
OperationBindingContext = new OperationBindingContext()
|
||||
{
|
||||
ActionContext = new ActionContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext()
|
||||
{
|
||||
RequestServices = new ServiceCollection().BuildServiceProvider(),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
var binder = CreateBinder(bindingContext.ModelMetadata);
|
||||
|
||||
// Act
|
||||
var result = binder.CanBindPropertyPublic(bindingContext, metadata);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(nameof(TypeWithIncludedPropertiesUsingBindAttribute.IncludedExplicitly1), true)]
|
||||
[InlineData(nameof(TypeWithIncludedPropertiesUsingBindAttribute.IncludedExplicitly2), true)]
|
||||
|
@ -1084,7 +1051,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
BinderModelName = metadata.BinderModelName,
|
||||
BinderType = metadata.BinderType,
|
||||
BindingSource = metadata.BindingSource,
|
||||
PropertyBindingPredicateProvider = metadata.PropertyBindingPredicateProvider,
|
||||
PropertyFilterProvider = metadata.PropertyFilterProvider,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -1284,17 +1251,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
public int IncludedExplicitly2 { get; set; }
|
||||
}
|
||||
|
||||
[Bind(typeof(ExcludedProvider))]
|
||||
private class TypeWithExcludedPropertiesUsingBindAttribute
|
||||
{
|
||||
public int Excluded1 { get; set; }
|
||||
|
||||
public int Excluded2 { get; set; }
|
||||
|
||||
public int IncludedByDefault1 { get; set; }
|
||||
public int IncludedByDefault2 { get; set; }
|
||||
}
|
||||
|
||||
private class Document
|
||||
{
|
||||
[NonValueBinderMetadata]
|
||||
|
@ -1317,15 +1273,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
public BindingSource BindingSource { get { return BindingSource.Query; } }
|
||||
}
|
||||
|
||||
private class ExcludedProvider : IPropertyBindingPredicateProvider
|
||||
private class ExcludedProvider : IPropertyFilterProvider
|
||||
{
|
||||
public Func<ModelBindingContext, string, bool> PropertyFilter
|
||||
public Func<ModelMetadata, bool> PropertyFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
return (context, propertyName) =>
|
||||
!string.Equals("Excluded1", propertyName, StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals("Excluded2", propertyName, StringComparison.OrdinalIgnoreCase);
|
||||
return (m) =>
|
||||
!string.Equals("Excluded1", m.PropertyName, StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals("Excluded2", m.PropertyName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
Assert.Null(metadata.BinderModelName);
|
||||
Assert.Null(metadata.BinderType);
|
||||
Assert.Null(metadata.BindingSource);
|
||||
Assert.Null(metadata.PropertyBindingPredicateProvider);
|
||||
Assert.Null(metadata.PropertyFilterProvider);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
@ -150,14 +150,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(UnsuccessfulModelBindingData))]
|
||||
public async Task TryUpdateModel_UsingIncludePredicateOverload_ReturnsFalse_IfBinderIsUnsuccessful(
|
||||
public async Task TryUpdateModel_UsingPropertyFilterOverload_ReturnsFalse_IfBinderIsUnsuccessful(
|
||||
ModelBindingResult? binderResult)
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
var binder = new StubModelBinder(binderResult);
|
||||
var model = new MyModel();
|
||||
Func<ModelBindingContext, string, bool> includePredicate = (context, propertyName) => true;
|
||||
Func<ModelMetadata, bool> propertyFilter = (m) => true;
|
||||
|
||||
// Act
|
||||
var result = await ModelBindingHelper.TryUpdateModelAsync(
|
||||
|
@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
new List<IInputFormatter>(),
|
||||
new Mock<IObjectModelValidator>(MockBehavior.Strict).Object,
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
includePredicate);
|
||||
propertyFilter);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
@ -180,7 +180,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryUpdateModel_UsingIncludePredicateOverload_ReturnsTrue_ModelBindsAndValidatesSuccessfully()
|
||||
public async Task TryUpdateModel_UsingPropertyFilterOverload_ReturnsTrue_ModelBindsAndValidatesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var binderProviders = new IModelBinderProvider[]
|
||||
|
@ -208,9 +208,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{ "ExcludedProperty", "ExcludedPropertyValue" }
|
||||
};
|
||||
|
||||
Func<ModelBindingContext, string, bool> includePredicate = (context, propertyName) =>
|
||||
string.Equals(propertyName, "IncludedProperty", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(propertyName, "MyProperty", StringComparison.OrdinalIgnoreCase);
|
||||
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
||||
string.Equals(m.PropertyName, "IncludedProperty", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(m.PropertyName, "MyProperty", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var valueProvider = new TestValueProvider(values);
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
|
@ -226,7 +226,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(metadataProvider, new ValidatorCache()),
|
||||
validator,
|
||||
includePredicate);
|
||||
propertyFilter);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
@ -491,14 +491,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(UnsuccessfulModelBindingData))]
|
||||
public async Task TryUpdateModelNonGeneric_PredicateOverload_ReturnsFalse_IfBinderIsUnsuccessful(
|
||||
public async Task TryUpdateModelNonGeneric_PropertyFilterOverload_ReturnsFalse_IfBinderIsUnsuccessful(
|
||||
ModelBindingResult? binderResult)
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
var binder = new StubModelBinder(binderResult);
|
||||
var model = new MyModel();
|
||||
Func<ModelBindingContext, string, bool> includePredicate = (context, propertyName) => true;
|
||||
Func<ModelMetadata, bool> propertyFilter = (m) => true;
|
||||
|
||||
// Act
|
||||
var result = await ModelBindingHelper.TryUpdateModelAsync(
|
||||
|
@ -512,7 +512,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
inputFormatters: new List<IInputFormatter>(),
|
||||
objectModelValidator: new Mock<IObjectModelValidator>(MockBehavior.Strict).Object,
|
||||
validatorProvider: Mock.Of<IModelValidatorProvider>(),
|
||||
predicate: includePredicate);
|
||||
propertyFilter: propertyFilter);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
@ -522,7 +522,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryUpdateModelNonGeneric_PredicateOverload_ReturnsTrue_ModelBindsAndValidatesSuccessfully()
|
||||
public async Task TryUpdateModelNonGeneric_PropertyFilterOverload_ReturnsTrue_ModelBindsAndValidatesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var binderProviders = new IModelBinderProvider[]
|
||||
|
@ -550,9 +550,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{ "ExcludedProperty", "ExcludedPropertyValue" }
|
||||
};
|
||||
|
||||
Func<ModelBindingContext, string, bool> includePredicate = (context, propertyName) =>
|
||||
string.Equals(propertyName, "IncludedProperty", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(propertyName, "MyProperty", StringComparison.OrdinalIgnoreCase);
|
||||
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
||||
string.Equals(m.PropertyName, "IncludedProperty", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(m.PropertyName, "MyProperty", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var valueProvider = new TestValueProvider(values);
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
|
@ -569,7 +569,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(metadataProvider, new ValidatorCache()),
|
||||
validator,
|
||||
includePredicate);
|
||||
propertyFilter);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
@ -657,7 +657,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
|
||||
var binder = new StubModelBinder();
|
||||
var model = new MyModel();
|
||||
Func<ModelBindingContext, string, bool> includePredicate = (context, propertyName) => true;
|
||||
Func<ModelMetadata, bool> propertyFilter = (m) => true;
|
||||
|
||||
// Act & Assert
|
||||
var exception = await Assert.ThrowsAsync<ArgumentException>(
|
||||
|
@ -672,7 +672,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(metadataProvider, new ValidatorCache()),
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
includePredicate));
|
||||
propertyFilter));
|
||||
|
||||
var expectedMessage = string.Format("The model's runtime type '{0}' is not assignable to the type '{1}'." +
|
||||
Environment.NewLine +
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
BinderModelName = Metadata.BinderModelName,
|
||||
BinderType = Metadata.BinderType,
|
||||
BindingSource = Metadata.BindingSource,
|
||||
PropertyBindingPredicateProvider = Metadata.PropertyBindingPredicateProvider,
|
||||
PropertyFilterProvider = Metadata.PropertyFilterProvider,
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations.Internal
|
|||
public class ModelMetadataProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void ModelMetadataProvider_UsesPredicateOnType()
|
||||
public void ModelMetadataProvider_UsesPropertyFilterProviderOnType()
|
||||
{
|
||||
// Arrange
|
||||
var type = typeof(User);
|
||||
|
@ -32,12 +32,12 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations.Internal
|
|||
var metadata = provider.GetMetadataForType(type);
|
||||
|
||||
// Assert
|
||||
var predicate = metadata.PropertyBindingPredicateProvider.PropertyFilter;
|
||||
var propertyFilter = metadata.PropertyFilterProvider.PropertyFilter;
|
||||
|
||||
var matched = new HashSet<string>();
|
||||
foreach (var property in metadata.Properties)
|
||||
{
|
||||
if (predicate(context, property.PropertyName))
|
||||
if (propertyFilter(property))
|
||||
{
|
||||
matched.Add(property.PropertyName);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче