public void IsRequired_SetToTrue_WithDataMemberIsRequiredTrue() { // Arrange var provider = new DataMemberRequiredBindingMetadataProvider(); var attributes = new object[] { new DataMemberAttribute() { IsRequired = true, } }; var key = ModelMetadataIdentity.ForProperty( typeof(string), nameof(ClassWithDataMemberIsRequiredTrue.StringProperty), typeof(ClassWithDataMemberIsRequiredTrue)); var context = new BindingMetadataProviderContext(key, attributes); // Act provider.GetBindingMetadata(context); // Assert Assert.True(context.BindingMetadata.IsRequired); }
public void GetBindingDetails_BindingBehaviorLeftAlone_ForAttributeOnPropertyType(bool initialValue) { // Arrange var typeAttributes = new object[] { new BindingBehaviorAttribute(BindingBehavior.Required), }; var context = new BindingMetadataProviderContext( ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)), new ModelAttributes(propertyAttributes: new object[0], typeAttributes: typeAttributes)); // These values shouldn't be changed since this is a Type-Metadata context.BindingMetadata.IsBindingAllowed = initialValue; context.BindingMetadata.IsBindingRequired = initialValue; var provider = new DefaultBindingMetadataProvider(); // Act provider.GetBindingMetadata(context); // Assert Assert.Equal(initialValue, context.BindingMetadata.IsBindingAllowed); Assert.Equal(initialValue, context.BindingMetadata.IsBindingRequired); }
public void IsRequired_LeftAlone_DataMemberIsRequiredFalse(bool?initialValue) { // Arrange var provider = new DataMemberRequiredBindingMetadataProvider(); var attributes = new object[] { new DataMemberAttribute() { IsRequired = false, } }; var key = ModelMetadataIdentity.ForProperty( typeof(string), nameof(ClassWithDataMemberIsRequiredFalse.StringProperty), typeof(ClassWithDataMemberIsRequiredFalse)); var context = new BindingMetadataProviderContext(key, attributes); context.BindingMetadata.IsRequired = initialValue; // Act provider.GetBindingMetadata(context); // Assert Assert.Equal(initialValue, context.BindingMetadata.IsRequired); }
public void IsBindingRequired_LeftAlone_WithoutDataContractAttribute(bool initialValue) { // Arrange var provider = new DataMemberRequiredBindingMetadataProvider(); var attributes = new object[] { new DataMemberAttribute() { IsRequired = true, } }; var key = ModelMetadataIdentity.ForProperty( typeof(string), nameof(ClassWithDataMemberIsRequiredTrueWithoutDataContract.StringProperty), typeof(ClassWithDataMemberIsRequiredTrueWithoutDataContract)); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0])); context.BindingMetadata.IsBindingRequired = initialValue; // Act provider.GetBindingMetadata(context); // Assert Assert.Equal(initialValue, context.BindingMetadata.IsBindingRequired); }
public void GetBindingDetails_OverrideBehaviorOnBaseClass_OverrideWithRequired_OnClass() { // Arrange var context = new BindingMetadataProviderContext( ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindRequiredOverridesInheritedBindNever)), new ModelAttributes(propertyAttributes: new object[0], typeAttributes: new object[0])); var provider = new DefaultBindingMetadataProvider(); // Act provider.GetBindingMetadata(context); // Assert Assert.True(context.BindingMetadata.IsBindingAllowed); Assert.True(context.BindingMetadata.IsBindingRequired); }
public void GetBindingDetails_FindsBindNever_OnContainerClass() { // Arrange var context = new BindingMetadataProviderContext( ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindNeverOnClass)), new ModelAttributes(propertyAttributes: new object[0], typeAttributes: new object[0])); var provider = new DefaultBindingMetadataProvider(); // Act provider.GetBindingMetadata(context); // Assert Assert.False(context.BindingMetadata.IsBindingAllowed); Assert.False(context.BindingMetadata.IsBindingRequired); }
public void GetBindingDetails_NoEditableAttribute_IsReadOnlyLeftAlone(bool?initialValue) { // Arrange var provider = new DataAnnotationsMetadataProvider(); var attributes = new Attribute[] { }; var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0])); context.BindingMetadata.IsReadOnly = initialValue; // Act provider.GetBindingMetadata(context); // Assert Assert.Equal(initialValue, context.BindingMetadata.IsReadOnly); }
public void GetBindingMetadata_RequiredAttribute_IsBindingRequiredLeftAlone(bool initialValue) { // Arrange var provider = new DataAnnotationsMetadataProvider(); var attributes = new Attribute[] { new RequiredAttribute() }; var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var context = new BindingMetadataProviderContext(key, new ModelAttributes(attributes, new object[0])); context.BindingMetadata.IsBindingRequired = initialValue; // Act provider.GetBindingMetadata(context); // Assert Assert.Equal(initialValue, context.BindingMetadata.IsBindingRequired); }
public void GetValidationMetadata_RequiredAttribute_SetsIsRequiredToTrue() { // Arrange var provider = new DataAnnotationsMetadataProvider(); var required = new RequiredAttribute(); var attributes = new Attribute[] { required }; var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0])); // Act provider.GetValidationMetadata(context); // Assert Assert.True(context.ValidationMetadata.IsRequired); }
public void GetBindingDetails_RequiredAttribute_SetsIsRequiredToTrue() { // Arrange var provider = new DataAnnotationsMetadataProvider(); var required = new RequiredAttribute(); var attributes = new Attribute[] { required }; var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var context = new BindingMetadataProviderContext(key, attributes); // Act provider.GetBindingMetadata(context); // Assert Assert.True(context.BindingMetadata.IsRequired); }
public void CreateMetadataForProperty() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var key = ModelMetadataIdentity.ForProperty(typeof(string), "Message", typeof(Exception)); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0], new object[0])); // Act var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Assert Assert.Equal(typeof(string), metadata.ModelType); Assert.Equal("Message", metadata.PropertyName); Assert.Equal(typeof(Exception), metadata.ContainerType); }
public void GetValidationDetails_MarkedWithModelValidator_ReturnsValidator() { // Arrange var provider = new DefaultValidationMetadataProvider(); var attribute = new TestModelValidationAttribute(); var attributes = new Attribute[] { attribute }; var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0])); // Act provider.GetValidationMetadata(context); // Assert var validatorMetadata = Assert.Single(context.ValidationMetadata.ValidatorMetadata); Assert.Same(attribute, validatorMetadata); }
public void PropertiesProperty_CallsProvider() { // Arrange var provider = new Mock <IModelMetadataProvider>(MockBehavior.Strict); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var expectedProperties = new DefaultModelMetadata[] { new DefaultModelMetadata( provider.Object, detailsProvider, new DefaultMetadataDetails( ModelMetadataIdentity.ForProperty(typeof(int), "Prop1", typeof(string)), attributes: new ModelAttributes(new object[0], new object[0]))), new DefaultModelMetadata( provider.Object, detailsProvider, new DefaultMetadataDetails( ModelMetadataIdentity.ForProperty(typeof(int), "Prop2", typeof(string)), attributes: new ModelAttributes(new object[0], new object[0]))), }; provider .Setup(p => p.GetMetadataForProperties(typeof(string))) .Returns(expectedProperties); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0])); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); // Act var properties = metadata.Properties; // Assert Assert.Equal(expectedProperties.Length, properties.Count); for (var i = 0; i < expectedProperties.Length; i++) { Assert.Same(expectedProperties[i], properties[i]); } }
public void GetValidationDetails_ValidatableObject_AlreadyInContext_Ignores() { // Arrange var provider = new DataAnnotationsMetadataProvider(); var attribute = new TestValidationAttribute(); var attributes = new Attribute[] { attribute }; var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)); var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0])); context.ValidationMetadata.ValidatorMetadata.Add(attribute); // Act provider.GetValidationMetadata(context); // Assert var validatorMetadata = Assert.Single(context.ValidationMetadata.ValidatorMetadata); Assert.Same(attribute, validatorMetadata); }
public void PropertiesProperty_OrdersPropertyNamesUsingOrder_ThenAsProvided( IEnumerable <KeyValuePair <string, int> > originalNamesAndOrders, IEnumerable <string> expectedNames) { // Arrange var provider = new Mock <IModelMetadataProvider>(MockBehavior.Strict); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var expectedProperties = new List <DefaultModelMetadata>(); foreach (var kvp in originalNamesAndOrders) { var propertyCache = new DefaultMetadataDetails( ModelMetadataIdentity.ForProperty(typeof(int), kvp.Key, typeof(string)), attributes: new ModelAttributes(new object[0], new object[0])); propertyCache.DisplayMetadata = new DisplayMetadata(); propertyCache.DisplayMetadata.Order = kvp.Value; expectedProperties.Add(new DefaultModelMetadata( provider.Object, detailsProvider, propertyCache)); } provider .Setup(p => p.GetMetadataForProperties(typeof(string))) .Returns(expectedProperties); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0])); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); // Act var properties = metadata.Properties; // Assert Assert.Equal(expectedNames.Count(), properties.Count); Assert.Equal(expectedNames.ToArray(), properties.Select(p => p.PropertyName).ToArray()); }
public void GetBindingDetails_FindsBindRequired_OnProperty() { // Arrange var propertyAttributes = new object[] { new BindRequiredAttribute(), }; var context = new BindingMetadataProviderContext( ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)), new ModelAttributes(propertyAttributes, typeAttributes: new object[0])); var provider = new DefaultBindingMetadataProvider(); // Act provider.GetBindingMetadata(context); // Assert Assert.True(context.BindingMetadata.IsBindingAllowed); Assert.True(context.BindingMetadata.IsBindingRequired); }
public void GetBindingDetails_OverrideBehaviorOnClass_OverrideWithOptional() { // Arrange var propertyAttributes = new object[] { new BindingBehaviorAttribute(BindingBehavior.Optional) }; var context = new BindingMetadataProviderContext( ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindNeverOnClass)), new ModelAttributes(propertyAttributes, typeAttributes: new object[0])); var provider = new DefaultBindingMetadataProvider(); // Act provider.GetBindingMetadata(context); // Assert Assert.True(context.BindingMetadata.IsBindingAllowed); Assert.False(context.BindingMetadata.IsBindingRequired); }
public void GetBindingDetails_UsesFirstAttribute() { // Arrange var propertyAttributes = new object[] { new BindingBehaviorAttribute(BindingBehavior.Required), new BindNeverAttribute(), }; var context = new BindingMetadataProviderContext( ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)), new ModelAttributes(propertyAttributes, typeAttributes: new object[0])); var provider = new DefaultBindingMetadataProvider(CreateMessageProvider()); // Act provider.GetBindingMetadata(context); // Assert Assert.True(context.BindingMetadata.IsBindingAllowed); Assert.True(context.BindingMetadata.IsBindingRequired); }
/// <summary> /// Creates the <see cref="DefaultMetadataDetails"/> entries for the properties of a model /// <see cref="Type"/>. /// </summary> /// <param name="key"> /// The <see cref="ModelMetadataIdentity"/> identifying the model <see cref="Type"/>. /// </param> /// <returns>A details object for each property of the model <see cref="Type"/>.</returns> /// <remarks> /// The results of this method will be cached and used to satisfy calls to /// <see cref="GetMetadataForProperties(Type)"/>. Override this method to provide a different /// set of property data. /// </remarks> protected virtual DefaultMetadataDetails[] CreatePropertyDetails(ModelMetadataIdentity key) { var propertyHelpers = PropertyHelper.GetVisibleProperties(key.ModelType); var propertyEntries = new List <DefaultMetadataDetails>(propertyHelpers.Length); for (var i = 0; i < propertyHelpers.Length; i++) { var propertyHelper = propertyHelpers[i]; var propertyKey = ModelMetadataIdentity.ForProperty( propertyHelper.Property.PropertyType, propertyHelper.Name, key.ModelType); var attributes = ModelAttributes.GetAttributesForProperty( key.ModelType, propertyHelper.Property); var propertyEntry = new DefaultMetadataDetails(propertyKey, attributes); if (propertyHelper.Property.CanRead && propertyHelper.Property.GetMethod?.IsPublic == true) { var getter = PropertyHelper.MakeNullSafeFastPropertyGetter(propertyHelper.Property); propertyEntry.PropertyGetter = getter; } if (propertyHelper.Property.CanWrite && propertyHelper.Property.SetMethod?.IsPublic == true && !key.ModelType.GetTypeInfo().IsValueType) { propertyEntry.PropertySetter = propertyHelper.ValueSetter; } propertyEntries.Add(propertyEntry); } return(propertyEntries.ToArray()); }
public void PropertiesProperty_WithDefaultOrder_OrdersPropertyNamesAsProvided( IEnumerable <string> originalNames, IEnumerable <string> expectedNames) { // Arrange var provider = new Mock <IModelMetadataProvider>(MockBehavior.Strict); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var expectedProperties = new List <DefaultModelMetadata>(); foreach (var originalName in originalNames) { expectedProperties.Add(new DefaultModelMetadata( provider.Object, detailsProvider, new DefaultMetadataDetailsCache( ModelMetadataIdentity.ForProperty(typeof(int), originalName, typeof(string)), attributes: null))); } provider .Setup(p => p.GetMetadataForProperties(typeof(string))) .Returns(expectedProperties); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); // Act var properties = metadata.Properties; // Assert Assert.Equal(expectedNames.Count(), properties.Count); Assert.Equal(expectedNames.ToArray(), properties.Select(p => p.PropertyName).ToArray()); }
/// <summary> /// Creates the <see cref="DefaultMetadataDetailsCache"/> entries for the properties of a model /// <see cref="Type"/>. /// </summary> /// <param name="key"> /// The <see cref="ModelMetadataIdentity"/> identifying the model <see cref="Type"/>. /// </param> /// <returns>A cache object for each property of the model <see cref="Type"/>.</returns> /// <remarks> /// The results of this method will be cached and used to satisfy calls to /// <see cref="GetMetadataForProperties(Type)"/>. Override this method to provide a different /// set of property data. /// </remarks> protected virtual DefaultMetadataDetailsCache[] CreatePropertyCacheEntries([NotNull] ModelMetadataIdentity key) { var propertyHelpers = PropertyHelper.GetProperties(key.ModelType); var propertyEntries = new List <DefaultMetadataDetailsCache>(propertyHelpers.Length); for (var i = 0; i < propertyHelpers.Length; i++) { var propertyHelper = propertyHelpers[i]; if (propertyHelper.Property.DeclaringType != key.ModelType) { // If this property was declared on a base type then look for the definition closest to the // the model type to see if we should include it. var ignoreProperty = false; // Walk up the hierarchy until we find the type that actally declares this // PropertyInfo. var currentType = key.ModelType.GetTypeInfo(); while (currentType != propertyHelper.Property.DeclaringType.GetTypeInfo()) { // We've found a 'more proximal' public definition var declaredProperty = currentType.GetDeclaredProperty(propertyHelper.Name); if (declaredProperty != null) { ignoreProperty = true; break; } currentType = currentType.BaseType.GetTypeInfo(); } if (ignoreProperty) { // There's a better definition, ignore this. continue; } } var propertyKey = ModelMetadataIdentity.ForProperty( propertyHelper.Property.PropertyType, propertyHelper.Name, key.ModelType); var attributes = new List <object>(ModelAttributes.GetAttributesForProperty( key.ModelType, propertyHelper.Property)); var propertyEntry = new DefaultMetadataDetailsCache(propertyKey, attributes); if (propertyHelper.Property.CanRead && propertyHelper.Property.GetMethod?.IsPrivate == true) { propertyEntry.PropertyAccessor = PropertyHelper.MakeFastPropertyGetter(propertyHelper.Property); } if (propertyHelper.Property.CanWrite && propertyHelper.Property.SetMethod?.IsPrivate == true) { propertyEntry.PropertySetter = PropertyHelper.MakeFastPropertySetter(propertyHelper.Property); } propertyEntries.Add(propertyEntry); } return(propertyEntries.ToArray()); }