Add more details to ModelAttributes

This change adds more information to ModelAttributes, so that metadata
providers can look at the attributes on the property and type separately
if so desired
This commit is contained in:
Ryan Nowak 2015-04-16 16:25:25 -07:00
parent a4fd51772f
commit 2719111453
18 changed files with 285 additions and 133 deletions

View File

@ -18,10 +18,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// <param name="attributes">The attributes for the <see cref="ModelMetadata"/>.</param> /// <param name="attributes">The attributes for the <see cref="ModelMetadata"/>.</param>
public BindingMetadataProviderContext( public BindingMetadataProviderContext(
[NotNull] ModelMetadataIdentity key, [NotNull] ModelMetadataIdentity key,
[NotNull] IReadOnlyList<object> attributes) [NotNull] ModelAttributes attributes)
{ {
Key = key; Key = key;
Attributes = attributes; Attributes = attributes.Attributes;
PropertyAttributes = attributes.PropertyAttributes;
TypeAttributes = attributes.TypeAttributes;
BindingMetadata = new BindingMetadata(); BindingMetadata = new BindingMetadata();
} }
@ -35,6 +38,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// </summary> /// </summary>
public ModelMetadataIdentity Key { get; } public ModelMetadataIdentity Key { get; }
/// <summary>
/// Gets the property attributes.
/// </summary>
public IReadOnlyList<object> PropertyAttributes { get; }
/// <summary>
/// Gets the type attributes.
/// </summary>
public IReadOnlyList<object> TypeAttributes { get; }
/// <summary> /// <summary>
/// Gets the <see cref="Metadata.BindingMetadata"/>. /// Gets the <see cref="Metadata.BindingMetadata"/>.
/// </summary> /// </summary>

View File

@ -29,7 +29,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
} }
var dataMemberAttribute = context var dataMemberAttribute = context
.Attributes .PropertyAttributes
.OfType<DataMemberAttribute>() .OfType<DataMemberAttribute>()
.FirstOrDefault(); .FirstOrDefault();
if (dataMemberAttribute == null || !dataMemberAttribute.IsRequired) if (dataMemberAttribute == null || !dataMemberAttribute.IsRequired)

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic; using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{ {
@ -19,16 +19,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// </summary> /// </summary>
/// <param name="key">The <see cref="ModelMetadataIdentity"/>.</param> /// <param name="key">The <see cref="ModelMetadataIdentity"/>.</param>
/// <param name="attributes">The set of model attributes.</param> /// <param name="attributes">The set of model attributes.</param>
public DefaultMetadataDetails(ModelMetadataIdentity key, IReadOnlyList<object> attributes) public DefaultMetadataDetails(ModelMetadataIdentity key, [NotNull] ModelAttributes attributes)
{ {
Key = key; Key = key;
Attributes = attributes; ModelAttributes = attributes;
} }
/// <summary> /// <summary>
/// Gets or sets the set of model attributes. /// Gets or sets the set of model attributes.
/// </summary> /// </summary>
public IReadOnlyList<object> Attributes { get; } public ModelAttributes ModelAttributes { get; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="Metadata.BindingMetadata"/>. /// Gets or sets the <see cref="Metadata.BindingMetadata"/>.

View File

@ -44,11 +44,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// <summary> /// <summary>
/// Gets the set of attributes for the current instance. /// Gets the set of attributes for the current instance.
/// </summary> /// </summary>
public IReadOnlyList<object> Attributes public ModelAttributes Attributes
{ {
get get
{ {
return _details.Attributes; return _details.ModelAttributes;
} }
} }
@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{ {
if (_details.BindingMetadata == null) if (_details.BindingMetadata == null)
{ {
var context = new BindingMetadataProviderContext(Identity, _details.Attributes); var context = new BindingMetadataProviderContext(Identity, _details.ModelAttributes);
_detailsProvider.GetBindingMetadata(context); _detailsProvider.GetBindingMetadata(context);
_details.BindingMetadata = context.BindingMetadata; _details.BindingMetadata = context.BindingMetadata;
} }
@ -85,7 +85,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{ {
if (_details.DisplayMetadata == null) if (_details.DisplayMetadata == null)
{ {
var context = new DisplayMetadataProviderContext(Identity, _details.Attributes); var context = new DisplayMetadataProviderContext(Identity, _details.ModelAttributes);
_detailsProvider.GetDisplayMetadata(context); _detailsProvider.GetDisplayMetadata(context);
_details.DisplayMetadata = context.DisplayMetadata; _details.DisplayMetadata = context.DisplayMetadata;
} }
@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{ {
if (_details.ValidationMetadata == null) if (_details.ValidationMetadata == null)
{ {
var context = new ValidationMetadataProviderContext(Identity, _details.Attributes); var context = new ValidationMetadataProviderContext(Identity, _details.ModelAttributes);
_detailsProvider.GetValidationMetadata(context); _detailsProvider.GetValidationMetadata(context);
_details.ValidationMetadata = context.ValidationMetadata; _details.ValidationMetadata = context.ValidationMetadata;
} }

View File

@ -114,9 +114,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
propertyHelper.Name, propertyHelper.Name,
key.ModelType); key.ModelType);
var attributes = new List<object>(ModelAttributes.GetAttributesForProperty( var attributes = ModelAttributes.GetAttributesForProperty(
key.ModelType, key.ModelType,
propertyHelper.Property)); propertyHelper.Property);
var propertyEntry = new DefaultMetadataDetails(propertyKey, attributes); var propertyEntry = new DefaultMetadataDetails(propertyKey, attributes);
if (propertyHelper.Property.CanRead && propertyHelper.Property.GetMethod?.IsPublic == true) if (propertyHelper.Property.CanRead && propertyHelper.Property.GetMethod?.IsPublic == true)
@ -151,8 +151,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// </remarks> /// </remarks>
protected virtual DefaultMetadataDetails CreateTypeDetails([NotNull] ModelMetadataIdentity key) protected virtual DefaultMetadataDetails CreateTypeDetails([NotNull] ModelMetadataIdentity key)
{ {
var attributes = new List<object>(ModelAttributes.GetAttributesForType(key.ModelType)); return new DefaultMetadataDetails(key, ModelAttributes.GetAttributesForType(key.ModelType));
return new DefaultMetadataDetails(key, attributes);
} }
private class TypeCache : ConcurrentDictionary<ModelMetadataIdentity, ModelMetadataCacheEntry> private class TypeCache : ConcurrentDictionary<ModelMetadataIdentity, ModelMetadataCacheEntry>

View File

@ -18,10 +18,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// <param name="attributes">The attributes for the <see cref="ModelMetadata"/>.</param> /// <param name="attributes">The attributes for the <see cref="ModelMetadata"/>.</param>
public DisplayMetadataProviderContext( public DisplayMetadataProviderContext(
[NotNull] ModelMetadataIdentity key, [NotNull] ModelMetadataIdentity key,
[NotNull] IReadOnlyList<object> attributes) [NotNull] ModelAttributes attributes)
{ {
Key = key; Key = key;
Attributes = attributes; Attributes = attributes.Attributes;
PropertyAttributes = attributes.PropertyAttributes;
TypeAttributes = attributes.TypeAttributes;
DisplayMetadata = new DisplayMetadata(); DisplayMetadata = new DisplayMetadata();
} }
@ -30,14 +33,24 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// </summary> /// </summary>
public IReadOnlyList<object> Attributes { get; } public IReadOnlyList<object> Attributes { get; }
/// <summary>
/// Gets the <see cref="Metadata.DisplayMetadata"/>.
/// </summary>
public DisplayMetadata DisplayMetadata { get; }
/// <summary> /// <summary>
/// Gets the <see cref="ModelMetadataIdentity"/>. /// Gets the <see cref="ModelMetadataIdentity"/>.
/// </summary> /// </summary>
public ModelMetadataIdentity Key { get; } public ModelMetadataIdentity Key { get; }
/// <summary> /// <summary>
/// Gets the <see cref="Metadata.DisplayMetadata"/>. /// Gets the property attributes.
/// </summary> /// </summary>
public DisplayMetadata DisplayMetadata { get; } public IReadOnlyList<object> PropertyAttributes { get; }
/// <summary>
/// Gets the type attributes.
/// </summary>
public IReadOnlyList<object> TypeAttributes { get; }
} }
} }

View File

@ -10,27 +10,53 @@ using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
/// <summary> /// <summary>
/// Provides static methods which can be used to get a combined list of attributes associated /// Provides access to the combined list of attributes associated a <see cref="Type"/> or property.
/// with a parameter or property.
/// </summary> /// </summary>
public static class ModelAttributes public class ModelAttributes
{ {
/// <summary> /// <summary>
/// Gets the attributes for the given <paramref name="parameter"/>. /// Creates a new <see cref="ModelAttributes"/> for a <see cref="Type"/>.
/// </summary> /// </summary>
/// <param name="parameter">A <see cref="ParameterInfo"/> for which attributes need to be resolved. /// <param name="typeAttributes">The set of attributes for the <see cref="Type"/>.</param>
/// </param> public ModelAttributes([NotNull] IEnumerable<object> typeAttributes)
/// <returns>An <see cref="IEnumerable{object}"/> containing the attributes on the
/// <paramref name="parameter"/> before the attributes on the <paramref name="parameter"/> type.</returns>
public static IEnumerable<object> GetAttributesForParameter(ParameterInfo parameter)
{ {
// Return the parameter attributes first. Attributes = typeAttributes.ToArray();
var parameterAttributes = parameter.GetCustomAttributes(); TypeAttributes = Attributes;
var typeAttributes = parameter.ParameterType.GetTypeInfo().GetCustomAttributes();
return parameterAttributes.Concat(typeAttributes);
} }
/// <summary>
/// Creates a new <see cref="ModelAttributes"/> for a property.
/// </summary>
/// <param name="propertyAttributes">The set of attributes for the property.</param>
/// <param name="typeAttributes">
/// The set of attributes for the property's <see cref="Type"/>. See <see cref="PropertyInfo.PropertyType"/>.
/// </param>
public ModelAttributes([NotNull] IEnumerable<object> propertyAttributes, [NotNull] IEnumerable<object> typeAttributes)
{
PropertyAttributes = propertyAttributes.ToArray();
TypeAttributes = typeAttributes.ToArray();
Attributes = PropertyAttributes.Concat(TypeAttributes).ToArray();
}
/// <summary>
/// Gets the set of all attributes. If this instance represents the attributes for a property, the attributes
/// on the property definition are before those on the property's <see cref="Type"/>.
/// </summary>
public IReadOnlyList<object> Attributes { get; }
/// <summary>
/// Gets the set of attributes on the property, or <c>null</c> if this instance represents the attributes
/// for a <see cref="Type"/>.
/// </summary>
public IReadOnlyList<object> PropertyAttributes { get; }
/// <summary>
/// Gets the set of attributes on the <see cref="Type"/>. If this instance represents a property,
/// then <see cref="TypeAttributes"/> contains attributes retrieved from
/// <see cref="PropertyInfo.PropertyType"/>.
/// </summary>
public IReadOnlyList<object> TypeAttributes { get; }
/// <summary> /// <summary>
/// Gets the attributes for the given <paramref name="property"/>. /// Gets the attributes for the given <paramref name="property"/>.
/// </summary> /// </summary>
@ -38,32 +64,26 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// </param> /// </param>
/// <param name="property">A <see cref="PropertyInfo"/> for which attributes need to be resolved. /// <param name="property">A <see cref="PropertyInfo"/> for which attributes need to be resolved.
/// </param> /// </param>
/// <returns>An <see cref="IEnumerable{object}"/> containing the attributes on the /// <returns>A <see cref="ModelAttributes"/> instance with the attributes of the property.</returns>
/// <paramref name="property"/> before the attributes on the <paramref name="property"/> type.</returns> public static ModelAttributes GetAttributesForProperty([NotNull] Type type, [NotNull] PropertyInfo property)
public static IEnumerable<object> GetAttributesForProperty([NotNull] Type type, [NotNull] PropertyInfo property)
{ {
// Return the property attributes first.
var propertyAttributes = property.GetCustomAttributes(); var propertyAttributes = property.GetCustomAttributes();
var typeAttributes = property.PropertyType.GetTypeInfo().GetCustomAttributes(); var typeAttributes = property.PropertyType.GetTypeInfo().GetCustomAttributes();
propertyAttributes = propertyAttributes.Concat(typeAttributes); var metadataType = GetMetadataType(type);
if (metadataType != null)
var modelMedatadataType = type.GetTypeInfo().GetCustomAttribute<ModelMetadataTypeAttribute>();
if (modelMedatadataType != null)
{ {
var modelMedatadataProperty = modelMedatadataType.MetadataType.GetRuntimeProperty(property.Name); var metadataProperty = metadataType.GetRuntimeProperty(property.Name);
if (modelMedatadataProperty != null) if (metadataProperty != null)
{ {
var modelMedatadataAttributes = modelMedatadataProperty.GetCustomAttributes(); propertyAttributes = propertyAttributes.Concat(metadataProperty.GetCustomAttributes());
propertyAttributes = propertyAttributes.Concat(modelMedatadataAttributes);
var modelMetadataTypeAttributes = var propertyMetadataType = metadataProperty.PropertyType;
modelMedatadataProperty.PropertyType.GetTypeInfo().GetCustomAttributes(); typeAttributes = typeAttributes.Concat(propertyMetadataType.GetTypeInfo().GetCustomAttributes());
propertyAttributes = propertyAttributes.Concat(modelMetadataTypeAttributes);
} }
} }
return propertyAttributes; return new ModelAttributes(propertyAttributes, typeAttributes);
} }
/// <summary> /// <summary>
@ -71,20 +91,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// </summary> /// </summary>
/// <param name="type">The <see cref="Type"/> for which attributes need to be resolved. /// <param name="type">The <see cref="Type"/> for which attributes need to be resolved.
/// </param> /// </param>
/// <returns>An <see cref="IEnumerable{object}"/> containing the attributes on the /// <returns>A <see cref="ModelAttributes"/> instance with the attributes of the <see cref="Type"/>.</returns>
/// <paramref name="type"/>.</returns> public static ModelAttributes GetAttributesForType([NotNull] Type type)
public static IEnumerable<object> GetAttributesForType([NotNull] Type type)
{ {
var attributes = type.GetTypeInfo().GetCustomAttributes(); var attributes = type.GetTypeInfo().GetCustomAttributes();
var modelMedatadataType = type.GetTypeInfo().GetCustomAttribute<ModelMetadataTypeAttribute>(); var metadataType = GetMetadataType(type);
if (modelMedatadataType != null) if (metadataType != null)
{ {
var modelMedatadataAttributes = modelMedatadataType.MetadataType.GetTypeInfo().GetCustomAttributes(); attributes = attributes.Concat(metadataType.GetTypeInfo().GetCustomAttributes());
attributes = attributes.Concat(modelMedatadataAttributes);
} }
return attributes; return new ModelAttributes(attributes);
}
private static Type GetMetadataType(Type type)
{
return type.GetTypeInfo().GetCustomAttribute<ModelMetadataTypeAttribute>()?.MetadataType;
} }
} }
} }

View File

@ -18,10 +18,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// <param name="attributes">The attributes for the <see cref="ModelMetadata"/>.</param> /// <param name="attributes">The attributes for the <see cref="ModelMetadata"/>.</param>
public ValidationMetadataProviderContext( public ValidationMetadataProviderContext(
[NotNull] ModelMetadataIdentity key, [NotNull] ModelMetadataIdentity key,
[NotNull] IReadOnlyList<object> attributes) [NotNull] ModelAttributes attributes)
{ {
Key = key; Key = key;
Attributes = attributes; Attributes = attributes.Attributes;
PropertyAttributes = attributes.PropertyAttributes;
TypeAttributes = attributes.TypeAttributes;
ValidationMetadata = new ValidationMetadata(); ValidationMetadata = new ValidationMetadata();
} }
@ -35,6 +38,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
/// </summary> /// </summary>
public ModelMetadataIdentity Key { get; } public ModelMetadataIdentity Key { get; }
/// <summary>
/// Gets the property attributes.
/// </summary>
public IReadOnlyList<object> PropertyAttributes { get; }
/// <summary>
/// Gets the type attributes.
/// </summary>
public IReadOnlyList<object> TypeAttributes { get; }
/// <summary> /// <summary>
/// Gets the <see cref="Metadata.ValidationMetadata"/>. /// Gets the <see cref="Metadata.ValidationMetadata"/>.
/// </summary> /// </summary>

View File

@ -13,5 +13,8 @@
<PropertyGroup> <PropertyGroup>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project> </Project>

View File

@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var provider = new DataAnnotationsMetadataProvider(); var provider = new DataAnnotationsMetadataProvider();
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var context = new DisplayMetadataProviderContext(key, new object[] { attribute }); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(new object[] { attribute }));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -78,7 +78,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new[] { dataType, }; var attributes = new[] { dataType, };
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var context = new DisplayMetadataProviderContext(key, attributes); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { dataType, displayFormat, }; var attributes = new Attribute[] { dataType, displayFormat, };
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var context = new DisplayMetadataProviderContext(key, attributes); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -120,7 +120,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { editable }; var attributes = new Attribute[] { editable };
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var context = new BindingMetadataProviderContext(key, attributes); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetBindingMetadata(context); provider.GetBindingMetadata(context);
@ -139,7 +139,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { editable }; var attributes = new Attribute[] { editable };
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var context = new BindingMetadataProviderContext(key, attributes); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetBindingMetadata(context); provider.GetBindingMetadata(context);
@ -169,7 +169,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { display }; var attributes = new Attribute[] { display };
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var context = new DisplayMetadataProviderContext(key, attributes); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -198,7 +198,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { display }; var attributes = new Attribute[] { display };
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var context = new DisplayMetadataProviderContext(key, attributes); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -232,7 +232,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var key = ModelMetadataIdentity.ForType(type); var key = ModelMetadataIdentity.ForType(type);
var attributes = new object[0]; var attributes = new object[0];
var context = new DisplayMetadataProviderContext(key, attributes); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -266,7 +266,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var key = ModelMetadataIdentity.ForType(type); var key = ModelMetadataIdentity.ForType(type);
var attributes = new object[0]; var attributes = new object[0];
var context = new DisplayMetadataProviderContext(key, attributes); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -398,7 +398,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var key = ModelMetadataIdentity.ForType(type); var key = ModelMetadataIdentity.ForType(type);
var attributes = new object[0]; var attributes = new object[0];
var context = new DisplayMetadataProviderContext(key, attributes); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -532,7 +532,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var key = ModelMetadataIdentity.ForType(type); var key = ModelMetadataIdentity.ForType(type);
var attributes = new object[0]; var attributes = new object[0];
var context = new DisplayMetadataProviderContext(key, attributes); var context = new DisplayMetadataProviderContext(key, new ModelAttributes(attributes));
// Act // Act
provider.GetDisplayMetadata(context); provider.GetDisplayMetadata(context);
@ -551,7 +551,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { required }; var attributes = new Attribute[] { required };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new ValidationMetadataProviderContext(key, attributes); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
// Act // Act
provider.GetValidationMetadata(context); provider.GetValidationMetadata(context);
@ -571,7 +571,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { }; var attributes = new Attribute[] { };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new ValidationMetadataProviderContext(key, attributes); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
context.ValidationMetadata.IsRequired = initialValue; context.ValidationMetadata.IsRequired = initialValue;
// Act // Act
@ -592,7 +592,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { new RequiredAttribute() }; var attributes = new Attribute[] { new RequiredAttribute() };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new BindingMetadataProviderContext(key, attributes); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
context.BindingMetadata.IsBindingRequired = initialValue; context.BindingMetadata.IsBindingRequired = initialValue;
// Act // Act
@ -613,7 +613,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attributes = new Attribute[] { }; var attributes = new Attribute[] { };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new BindingMetadataProviderContext(key, attributes); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
context.BindingMetadata.IsReadOnly = initialValue; context.BindingMetadata.IsReadOnly = initialValue;
// Act // Act
@ -632,7 +632,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attribute = new TestValidationAttribute(); var attribute = new TestValidationAttribute();
var attributes = new Attribute[] { attribute }; var attributes = new Attribute[] { attribute };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new ValidationMetadataProviderContext(key, attributes); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
// Act // Act
provider.GetValidationMetadata(context); provider.GetValidationMetadata(context);
@ -651,7 +651,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attribute = new TestValidationAttribute(); var attribute = new TestValidationAttribute();
var attributes = new Attribute[] { attribute }; var attributes = new Attribute[] { attribute };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new ValidationMetadataProviderContext(key, attributes); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
context.ValidationMetadata.ValidatorMetadata.Add(attribute); context.ValidationMetadata.ValidatorMetadata.Add(attribute);
// Act // Act

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
typeof(string), typeof(string),
nameof(ClassWithDataMemberIsRequiredTrue.StringProperty), nameof(ClassWithDataMemberIsRequiredTrue.StringProperty),
typeof(ClassWithDataMemberIsRequiredTrue)); typeof(ClassWithDataMemberIsRequiredTrue));
var context = new BindingMetadataProviderContext(key, attributes); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
// Act // Act
provider.GetBindingMetadata(context); provider.GetBindingMetadata(context);
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
typeof(string), typeof(string),
nameof(ClassWithDataMemberIsRequiredFalse.StringProperty), nameof(ClassWithDataMemberIsRequiredFalse.StringProperty),
typeof(ClassWithDataMemberIsRequiredFalse)); typeof(ClassWithDataMemberIsRequiredFalse));
var context = new BindingMetadataProviderContext(key, attributes); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
context.BindingMetadata.IsBindingRequired = initialValue; context.BindingMetadata.IsBindingRequired = initialValue;
@ -74,7 +74,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
}; };
var key = ModelMetadataIdentity.ForType(typeof(ClassWithDataMemberIsRequiredTrue)); var key = ModelMetadataIdentity.ForType(typeof(ClassWithDataMemberIsRequiredTrue));
var context = new BindingMetadataProviderContext(key, attributes); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
context.BindingMetadata.IsBindingRequired = initialValue; context.BindingMetadata.IsBindingRequired = initialValue;
@ -97,7 +97,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
typeof(string), typeof(string),
nameof(ClassWithoutAttributes.StringProperty), nameof(ClassWithoutAttributes.StringProperty),
typeof(ClassWithoutAttributes)); typeof(ClassWithoutAttributes));
var context = new BindingMetadataProviderContext(key, attributes: new object[0]); var context = new BindingMetadataProviderContext(key, new ModelAttributes(new object[0], new object[0]));
context.BindingMetadata.IsBindingRequired = initialValue; context.BindingMetadata.IsBindingRequired = initialValue;
@ -125,7 +125,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
typeof(string), typeof(string),
nameof(ClassWithDataMemberIsRequiredTrueWithoutDataContract.StringProperty), nameof(ClassWithDataMemberIsRequiredTrueWithoutDataContract.StringProperty),
typeof(ClassWithDataMemberIsRequiredTrueWithoutDataContract)); typeof(ClassWithDataMemberIsRequiredTrueWithoutDataContract));
var context = new BindingMetadataProviderContext(key, attributes); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
context.BindingMetadata.IsBindingRequired = initialValue; context.BindingMetadata.IsBindingRequired = initialValue;

View File

@ -18,8 +18,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
}; };
var context = new BindingMetadataProviderContext( var context = new BindingMetadataProviderContext(
ModelMetadataIdentity.ForType(typeof(string)), ModelMetadataIdentity.ForType(typeof(string)),
attributes); new ModelAttributes(attributes));
var provider = new DefaultBindingMetadataProvider(); var provider = new DefaultBindingMetadataProvider();
@ -43,7 +43,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var context = new BindingMetadataProviderContext( var context = new BindingMetadataProviderContext(
ModelMetadataIdentity.ForType(typeof(string)), ModelMetadataIdentity.ForType(typeof(string)),
attributes); new ModelAttributes(attributes));
var provider = new DefaultBindingMetadataProvider(); var provider = new DefaultBindingMetadataProvider();
@ -66,7 +66,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var context = new BindingMetadataProviderContext( var context = new BindingMetadataProviderContext(
ModelMetadataIdentity.ForType(typeof(string)), ModelMetadataIdentity.ForType(typeof(string)),
attributes); new ModelAttributes(attributes));
var provider = new DefaultBindingMetadataProvider(); var provider = new DefaultBindingMetadataProvider();
@ -90,7 +90,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var context = new BindingMetadataProviderContext( var context = new BindingMetadataProviderContext(
ModelMetadataIdentity.ForType(typeof(string)), ModelMetadataIdentity.ForType(typeof(string)),
attributes); new ModelAttributes(attributes));
var provider = new DefaultBindingMetadataProvider(); var provider = new DefaultBindingMetadataProvider();
@ -113,7 +113,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var context = new BindingMetadataProviderContext( var context = new BindingMetadataProviderContext(
ModelMetadataIdentity.ForType(typeof(string)), ModelMetadataIdentity.ForType(typeof(string)),
attributes); new ModelAttributes(attributes));
var provider = new DefaultBindingMetadataProvider(); var provider = new DefaultBindingMetadataProvider();
@ -137,7 +137,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var context = new BindingMetadataProviderContext( var context = new BindingMetadataProviderContext(
ModelMetadataIdentity.ForType(typeof(string)), ModelMetadataIdentity.ForType(typeof(string)),
attributes); new ModelAttributes(attributes));
var provider = new DefaultBindingMetadataProvider(); var provider = new DefaultBindingMetadataProvider();

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
// Assert // Assert
var defaultMetadata = Assert.IsType<DefaultModelMetadata>(metadata); var defaultMetadata = Assert.IsType<DefaultModelMetadata>(metadata);
var attribute = Assert.IsType<ModelAttribute>(Assert.Single(defaultMetadata.Attributes)); var attribute = Assert.IsType<ModelAttribute>(Assert.Single(defaultMetadata.Attributes.Attributes));
Assert.Equal("OnType", attribute.Value); Assert.Equal("OnType", attribute.Value);
} }
@ -121,7 +121,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
// Assert // Assert
var defaultMetadata = Assert.IsType<DefaultModelMetadata>(metadata); var defaultMetadata = Assert.IsType<DefaultModelMetadata>(metadata);
var attributes = defaultMetadata.Attributes.ToArray(); var attributes = defaultMetadata.Attributes.Attributes.ToArray();
Assert.Equal("OnProperty", Assert.IsType<ModelAttribute>(attributes[0]).Value); Assert.Equal("OnProperty", Assert.IsType<ModelAttribute>(attributes[0]).Value);
Assert.Equal("OnPropertyType", Assert.IsType<ModelAttribute>(attributes[1]).Value); Assert.Equal("OnPropertyType", Assert.IsType<ModelAttribute>(attributes[1]).Value);
} }

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
Enumerable.Empty<IMetadataDetailsProvider>()); Enumerable.Empty<IMetadataDetailsProvider>());
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
// Act // Act
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -76,7 +76,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
Enumerable.Empty<IMetadataDetailsProvider>()); Enumerable.Empty<IMetadataDetailsProvider>());
var key = ModelMetadataIdentity.ForType(typeof(Exception)); var key = ModelMetadataIdentity.ForType(typeof(Exception));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
// Act // Act
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -95,7 +95,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
var key = ModelMetadataIdentity.ForProperty(typeof(string), "Message", typeof(Exception)); var key = ModelMetadataIdentity.ForProperty(typeof(string), "Message", typeof(Exception));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0], new object[0]));
// Act // Act
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -117,7 +117,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
var key = ModelMetadataIdentity.ForType(modelType); var key = ModelMetadataIdentity.ForType(modelType);
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -138,7 +138,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
var key = ModelMetadataIdentity.ForType(modelType); var key = ModelMetadataIdentity.ForType(modelType);
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -164,13 +164,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
detailsProvider, detailsProvider,
new DefaultMetadataDetails( new DefaultMetadataDetails(
ModelMetadataIdentity.ForProperty(typeof(int), "Prop1", typeof(string)), ModelMetadataIdentity.ForProperty(typeof(int), "Prop1", typeof(string)),
attributes: null)), attributes: new ModelAttributes(new object[0], new object[0]))),
new DefaultModelMetadata( new DefaultModelMetadata(
provider.Object, provider.Object,
detailsProvider, detailsProvider,
new DefaultMetadataDetails( new DefaultMetadataDetails(
ModelMetadataIdentity.ForProperty(typeof(int), "Prop2", typeof(string)), ModelMetadataIdentity.ForProperty(typeof(int), "Prop2", typeof(string)),
attributes: null)), attributes: new ModelAttributes(new object[0], new object[0]))),
}; };
provider provider
@ -178,7 +178,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
.Returns(expectedProperties); .Returns(expectedProperties);
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache);
@ -240,7 +240,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
detailsProvider, detailsProvider,
new DefaultMetadataDetails( new DefaultMetadataDetails(
ModelMetadataIdentity.ForProperty(typeof(int), originalName, typeof(string)), ModelMetadataIdentity.ForProperty(typeof(int), originalName, typeof(string)),
attributes: null))); attributes: new ModelAttributes(new object[0], new object[0]))));
} }
provider provider
@ -248,7 +248,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
.Returns(expectedProperties); .Returns(expectedProperties);
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache);
@ -340,7 +340,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{ {
var propertyCache = new DefaultMetadataDetails( var propertyCache = new DefaultMetadataDetails(
ModelMetadataIdentity.ForProperty(typeof(int), kvp.Key, typeof(string)), ModelMetadataIdentity.ForProperty(typeof(int), kvp.Key, typeof(string)),
attributes: null); attributes: new ModelAttributes(new object[0], new object[0]));
propertyCache.DisplayMetadata = new DisplayMetadata(); propertyCache.DisplayMetadata = new DisplayMetadata();
propertyCache.DisplayMetadata.Order = kvp.Value; propertyCache.DisplayMetadata.Order = kvp.Value;
@ -356,7 +356,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
.Returns(expectedProperties); .Returns(expectedProperties);
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache);
@ -377,7 +377,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -398,7 +398,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
var key = ModelMetadataIdentity.ForType(typeof(string)); var key = ModelMetadataIdentity.ForType(typeof(string));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -419,7 +419,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var provider = new DefaultModelMetadataProvider(detailsProvider); var provider = new DefaultModelMetadataProvider(detailsProvider);
var key = ModelMetadataIdentity.ForType(typeof(int[])); var key = ModelMetadataIdentity.ForType(typeof(int[]));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -438,7 +438,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var provider = new DefaultModelMetadataProvider(detailsProvider); var provider = new DefaultModelMetadataProvider(detailsProvider);
var key = ModelMetadataIdentity.ForType(typeof(TypeWithProperties)); var key = ModelMetadataIdentity.ForType(typeof(TypeWithProperties));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -457,7 +457,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var provider = new DefaultModelMetadataProvider(detailsProvider); var provider = new DefaultModelMetadataProvider(detailsProvider);
var key = ModelMetadataIdentity.ForType(typeof(TypeWithProperties)); var key = ModelMetadataIdentity.ForType(typeof(TypeWithProperties));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
@ -476,7 +476,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var provider = new DefaultModelMetadataProvider(detailsProvider); var provider = new DefaultModelMetadataProvider(detailsProvider);
var key = ModelMetadataIdentity.ForType(typeof(TypeWithProperties)); var key = ModelMetadataIdentity.ForType(typeof(TypeWithProperties));
var cache = new DefaultMetadataDetails(key, new object[0]); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);

View File

@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attribute = new TestClientModelValidationAttribute(); var attribute = new TestClientModelValidationAttribute();
var attributes = new Attribute[] { attribute }; var attributes = new Attribute[] { attribute };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new ValidationMetadataProviderContext(key, attributes); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
// Act // Act
provider.GetValidationMetadata(context); provider.GetValidationMetadata(context);
@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attribute = new TestModelValidationAttribute(); var attribute = new TestModelValidationAttribute();
var attributes = new Attribute[] { attribute }; var attributes = new Attribute[] { attribute };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new ValidationMetadataProviderContext(key, attributes); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
// Act // Act
provider.GetValidationMetadata(context); provider.GetValidationMetadata(context);
@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var attribute = new TestValidationAttribute(); var attribute = new TestValidationAttribute();
var attributes = new Attribute[] { attribute }; var attributes = new Attribute[] { attribute };
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
var context = new ValidationMetadataProviderContext(key, attributes); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0]));
context.ValidationMetadata.ValidatorMetadata.Add(attribute); context.ValidationMetadata.ValidatorMetadata.Add(attribute);
// Act // Act

View File

@ -9,7 +9,7 @@ using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public class ModelMetadataAttributesTest public class ModelAttributesTest
{ {
[Fact] [Fact]
public void GetAttributesForBaseProperty_IncludesMetadataAttributes() public void GetAttributesForBaseProperty_IncludesMetadataAttributes()
@ -22,8 +22,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var attributes = ModelAttributes.GetAttributesForProperty(modelType, property); var attributes = ModelAttributes.GetAttributesForProperty(modelType, property);
// Assert // Assert
Assert.Single(attributes.OfType<RequiredAttribute>()); Assert.Single(attributes.Attributes.OfType<RequiredAttribute>());
Assert.Single(attributes.OfType<StringLengthAttribute>()); Assert.Single(attributes.Attributes.OfType<StringLengthAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<RequiredAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<StringLengthAttribute>());
} }
[Fact] [Fact]
@ -37,11 +40,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var attributes = ModelAttributes.GetAttributesForProperty(modelType, property); var attributes = ModelAttributes.GetAttributesForProperty(modelType, property);
// Assert // Assert
var rangeAttribute = attributes.OfType<RangeAttribute>().FirstOrDefault(); var rangeAttributes = attributes.Attributes.OfType<RangeAttribute>().ToArray();
Assert.NotNull(rangeAttribute); Assert.NotNull(rangeAttributes[0]);
Assert.Equal(0, (int)rangeAttribute.Minimum); Assert.Equal(0, (int)rangeAttributes[0].Minimum);
Assert.Equal(10, (int)rangeAttribute.Maximum); Assert.Equal(10, (int)rangeAttributes[0].Maximum);
Assert.Single(attributes.OfType<FromHeaderAttribute>()); Assert.NotNull(rangeAttributes[1]);
Assert.Equal(10, (int)rangeAttributes[1].Minimum);
Assert.Equal(100, (int)rangeAttributes[1].Maximum);
Assert.Single(attributes.Attributes.OfType<FromHeaderAttribute>());
rangeAttributes = attributes.PropertyAttributes.OfType<RangeAttribute>().ToArray();
Assert.NotNull(rangeAttributes[0]);
Assert.Equal(0, (int)rangeAttributes[0].Minimum);
Assert.Equal(10, (int)rangeAttributes[0].Maximum);
Assert.NotNull(rangeAttributes[1]);
Assert.Equal(10, (int)rangeAttributes[1].Minimum);
Assert.Equal(100, (int)rangeAttributes[1].Maximum);
Assert.Single(attributes.PropertyAttributes.OfType<FromHeaderAttribute>());
} }
[Fact] [Fact]
@ -55,8 +70,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var attributes = ModelAttributes.GetAttributesForProperty(modelType, property); var attributes = ModelAttributes.GetAttributesForProperty(modelType, property);
// Assert // Assert
Assert.Single(attributes.OfType<RequiredAttribute>()); Assert.Single(attributes.Attributes.OfType<RequiredAttribute>());
Assert.Single(attributes.OfType<StringLengthAttribute>()); Assert.Single(attributes.Attributes.OfType<StringLengthAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<RequiredAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<StringLengthAttribute>());
} }
[Fact] [Fact]
@ -70,9 +88,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var attributes = ModelAttributes.GetAttributesForProperty(modelType, property); var attributes = ModelAttributes.GetAttributesForProperty(modelType, property);
// Assert // Assert
Assert.Single(attributes.OfType<RequiredAttribute>()); Assert.Single(attributes.Attributes.OfType<RequiredAttribute>());
Assert.Single(attributes.OfType<StringLengthAttribute>()); Assert.Single(attributes.Attributes.OfType<StringLengthAttribute>());
Assert.DoesNotContain(typeof(RangeAttribute), attributes); Assert.DoesNotContain(typeof(RangeAttribute), attributes.Attributes);
Assert.Single(attributes.PropertyAttributes.OfType<RequiredAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<StringLengthAttribute>());
Assert.DoesNotContain(typeof(RangeAttribute), attributes.PropertyAttributes);
} }
[Fact] [Fact]
@ -86,8 +108,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var attributes = ModelAttributes.GetAttributesForProperty(modelType, property); var attributes = ModelAttributes.GetAttributesForProperty(modelType, property);
// Assert // Assert
Assert.Single(attributes.OfType<RequiredAttribute>()); Assert.Single(attributes.Attributes.OfType<RequiredAttribute>());
Assert.Single(attributes.OfType<RangeAttribute>()); Assert.Single(attributes.Attributes.OfType<RangeAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<RequiredAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<RangeAttribute>());
} }
[Fact] [Fact]
@ -101,8 +126,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var attributes = ModelAttributes.GetAttributesForProperty(modelType, property); var attributes = ModelAttributes.GetAttributesForProperty(modelType, property);
// Assert // Assert
Assert.Single(attributes.OfType<RequiredAttribute>()); Assert.Single(attributes.Attributes.OfType<RequiredAttribute>());
Assert.Single(attributes.OfType<FromServicesAttribute>()); Assert.Single(attributes.Attributes.OfType<FromServicesAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<RequiredAttribute>());
Assert.Single(attributes.PropertyAttributes.OfType<FromServicesAttribute>());
} }
[Fact] [Fact]
@ -112,10 +140,45 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var attributes = ModelAttributes.GetAttributesForType(typeof(BaseViewModel)); var attributes = ModelAttributes.GetAttributesForType(typeof(BaseViewModel));
// Assert // Assert
Assert.Single(attributes.OfType<ClassValidator>()); Assert.Single(attributes.Attributes.OfType<ClassValidator>());
Assert.Single(attributes.TypeAttributes.OfType<ClassValidator>());
} }
// Helper classes [Fact]
public void GetAttributesForType_PropertyAttributes_IsNull()
{
// Arrange & Act
var attributes = ModelAttributes.GetAttributesForType(typeof(BaseViewModel));
// Assert
Assert.Null(attributes.PropertyAttributes);
}
[Fact]
public void GetAttributesForProperty_MergedAttributes()
{
// Arrange
var property = typeof(MergedAttributes).GetRuntimeProperty(nameof(MergedAttributes.Property));
// Act
var attributes = ModelAttributes.GetAttributesForProperty(typeof(MergedAttributes), property);
// Assert
Assert.Equal(4, attributes.Attributes.Count);
Assert.IsType<RequiredAttribute>(attributes.Attributes[0]);
Assert.IsType<RangeAttribute>(attributes.Attributes[1]);
Assert.IsType<ClassValidator>(attributes.Attributes[2]);
Assert.IsType<BindAttribute>(attributes.Attributes[3]);
Assert.Equal(2, attributes.PropertyAttributes.Count);
Assert.IsType<RequiredAttribute>(attributes.PropertyAttributes[0]);
Assert.IsType<RangeAttribute>(attributes.PropertyAttributes[1]);
Assert.Equal(2, attributes.TypeAttributes.Count);
Assert.IsType<ClassValidator>(attributes.TypeAttributes[0]);
Assert.IsType<BindAttribute>(attributes.TypeAttributes[1]);
}
[ClassValidator] [ClassValidator]
private class BaseModel private class BaseModel
@ -182,5 +245,28 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return true; return true;
} }
} }
[ModelMetadataType(typeof(MergedAttributesMetadata))]
private class MergedAttributes
{
[Required]
public PropertyType Property { get; set; }
}
private class MergedAttributesMetadata
{
[Range(0, 10)]
public MetadataPropertyType Property { get; set; }
}
[ClassValidator]
private class PropertyType
{
}
[Bind]
private class MetadataPropertyType
{
}
} }
} }

View File

@ -886,7 +886,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
protected override DefaultMetadataDetails CreateTypeDetails([NotNull]ModelMetadataIdentity key) protected override DefaultMetadataDetails CreateTypeDetails([NotNull]ModelMetadataIdentity key)
{ {
var entry = base.CreateTypeDetails(key); var entry = base.CreateTypeDetails(key);
return new DefaultMetadataDetails(key, _attributes.Concat(entry.Attributes).ToArray()); return new DefaultMetadataDetails(
key,
new ModelAttributes(_attributes.Concat(entry.ModelAttributes.TypeAttributes).ToArray()));
} }
} }
} }

View File

@ -20,7 +20,7 @@ namespace ModelBindingWebSite
protected override Task<ModelBindingResult> BindModelCoreAsync(ModelBindingContext bindingContext) protected override Task<ModelBindingResult> BindModelCoreAsync(ModelBindingContext bindingContext)
{ {
var attributes = ((DefaultModelMetadata)bindingContext.ModelMetadata).Attributes; var attributes = ((DefaultModelMetadata)bindingContext.ModelMetadata).Attributes;
var metadata = attributes.OfType<FromTestAttribute>().First(); var metadata = attributes.Attributes.OfType<FromTestAttribute>().First();
var model = metadata.Value; var model = metadata.Value;
if (!IsSimpleType(bindingContext.ModelType)) if (!IsSimpleType(bindingContext.ModelType))
{ {