public void NullDisplayText_DoesNotCacheInitialDelegateValue()
        {
            // Arrange
            var provider        = new EmptyModelMetadataProvider();
            var detailsProvider = new EmptyCompositeMetadataDetailsProvider();

            var key = ModelMetadataIdentity.ForProperty(
                typeof(string),
                nameof(TypeWithProperties.PublicGetPublicSetProperty),
                typeof(TypeWithProperties));

            var attributes  = new ModelAttributes(Array.Empty <object>(), Array.Empty <object>(), null);
            var nullDisplay = "initial display text";
            var cache       = new DefaultMetadataDetails(key, attributes)
            {
                DisplayMetadata = new DisplayMetadata
                {
                    NullDisplayTextProvider = () => nullDisplay,
                },
            };

            var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);

            foreach (var newDisplay in new[] { "one", "two", "three" })
            {
                // Arrange n
                nullDisplay = newDisplay;

                // Act n
                var result = metadata.NullDisplayText;

                // Assert n
                Assert.Equal(newDisplay, result);
            }
        }
Example #2
0
        public void CreateBindingDetails_BindingBehaviorLeftAlone_ForAttributeOnPropertyType(bool initialValue)
        {
            // Arrange
            var typeAttributes = new object[]
            {
                new BindingBehaviorAttribute(BindingBehavior.Required),
            };

            var context = new BindingMetadataProviderContext(
                ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
                new ModelAttributes(typeAttributes, new object[0], null));

            // 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.CreateBindingMetadata(context);

            // Assert
            Assert.Equal(initialValue, context.BindingMetadata.IsBindingAllowed);
            Assert.Equal(initialValue, context.BindingMetadata.IsBindingRequired);
        }
        public void PropertyValidationFilter_Null_IfPropertyHasValidateNeverOnItsType()
        {
            // Arrange
            var provider = new DefaultValidationMetadataProvider();

            var attributes = new Attribute[] { new ValidateNeverAttribute() };
            var key        = ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string));
            var context    = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0], null));

            // Act
            provider.CreateValidationMetadata(context);

            // Assert
            Assert.Null(context.ValidationMetadata.PropertyValidationFilter);
        }
Example #4
0
        public void CreateBindingDetails_FindsBindRequired_OnContainerClass()
        {
            // Arrange
            var context = new BindingMetadataProviderContext(
                ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindRequiredOnClass)),
                new ModelAttributes(new object[0], new object[0], null));

            var provider = new DefaultBindingMetadataProvider();

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.True(context.BindingMetadata.IsBindingAllowed);
            Assert.True(context.BindingMetadata.IsBindingRequired);
        }
Example #5
0
        public void CreateBindingDetails_FindsBindNever_OnBaseClass()
        {
            // Arrange
            var context = new BindingMetadataProviderContext(
                ModelMetadataIdentity.ForProperty(typeof(BindNeverOnClass).GetProperty(nameof(BindNeverOnClass.Property)), typeof(int), typeof(BindNeverOnClass)),
                new ModelAttributes(new object[0], new object[0], null));

            var provider = new DefaultBindingMetadataProvider();

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.False(context.BindingMetadata.IsBindingAllowed);
            Assert.False(context.BindingMetadata.IsBindingRequired);
        }
Example #6
0
        public void CreateBindingDetails_OverrideBehaviorOnBaseClass_OverrideWithRequired_OnClass()
        {
            // Arrange
            var context = new BindingMetadataProviderContext(
                ModelMetadataIdentity.ForProperty(typeof(BindRequiredOverridesInheritedBindNever).GetProperty(nameof(BindRequiredOverridesInheritedBindNever.Property)), typeof(int), typeof(BindRequiredOverridesInheritedBindNever)),
                new ModelAttributes(new object[0], new object[0], null));

            var provider = new DefaultBindingMetadataProvider();

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.True(context.BindingMetadata.IsBindingAllowed);
            Assert.True(context.BindingMetadata.IsBindingRequired);
        }
        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(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string));
            var context    = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], attributes, null));

            // Act
            provider.CreateValidationMetadata(context);

            // Assert
            var validatorMetadata = Assert.Single(context.ValidationMetadata.ValidatorMetadata);

            Assert.Same(attribute, validatorMetadata);
        }
        public void PropertyValidationFilter_ShouldValidateEntry_False_IfPropertyHasValidateNever()
        {
            // Arrange
            var provider = new DefaultValidationMetadataProvider();

            var attributes = new Attribute[] { new ValidateNeverAttribute() };
            var key        = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
            var context    = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], attributes, null));

            // Act
            provider.CreateValidationMetadata(context);

            // Assert
            Assert.NotNull(context.ValidationMetadata.PropertyValidationFilter);
            Assert.False(context.ValidationMetadata.PropertyValidationFilter.ShouldValidateEntry(
                             new ValidationEntry(),
                             new ValidationEntry()));
        }
        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], null))
                {
                    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], null, null));

            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 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_Validator_AlreadyInContext_Ignores()
        {
            // Arrange
            var provider = new DefaultValidationMetadataProvider();

            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.CreateValidationMetadata(context);

            // Assert
            var validatorMetadata = Assert.Single(context.ValidationMetadata.ValidatorMetadata);

            Assert.Same(attribute, validatorMetadata);
        }
Example #13
0
        public void IsBindingAllowed_IsFalse_WhenTypeMatches(bool initialValue)
        {
            // Arrange
            var provider = new ExcludeBindingMetadataProvider(typeof(int));

            var key = ModelMetadataIdentity.ForProperty(
                typeof(Person).GetProperty(nameof(Person.Age)),
                typeof(int),
                typeof(Person));

            var context = new BindingMetadataProviderContext(key, new ModelAttributes(new object[0], new object[0], null));

            context.BindingMetadata.IsBindingAllowed = initialValue;

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.False(context.BindingMetadata.IsBindingAllowed);
        }
        public void IsBindingAllowed_LeftAlone_WhenTypeDoesntMatch(bool initialValue)
        {
            // Arrange
            var provider = new ExcludeBindingMetadataProvider(typeof(string));

            var key = ModelMetadataIdentity.ForProperty(
                typeof(int),
                nameof(Person.Age),
                typeof(Person));

            var context = new BindingMetadataProviderContext(key, new ModelAttributes(new object[0], new object[0]));

            context.BindingMetadata.IsBindingAllowed = initialValue;

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.Equal(initialValue, context.BindingMetadata.IsBindingAllowed);
        }
        public void PropertyValidationFilter_ShouldValidateEntry_False_IfContainingTypeInheritsValidateNever()
        {
            // Arrange
            var provider = new DefaultValidationMetadataProvider();

            var key = ModelMetadataIdentity.ForProperty(
                typeof(ValidateNeverSubclass).GetProperty(nameof(ValidateNeverSubclass.SubclassName)),
                typeof(string),
                typeof(ValidateNeverSubclass));
            var context = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], new object[0], null));

            // Act
            provider.CreateValidationMetadata(context);

            // Assert
            Assert.NotNull(context.ValidationMetadata.PropertyValidationFilter);
            Assert.False(context.ValidationMetadata.PropertyValidationFilter.ShouldValidateEntry(
                             new ValidationEntry(),
                             new ValidationEntry()));
        }
        /// <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,
                    propertyHelper.Property.PropertyType,
                    key.ModelType);

                var propertyEntry = CreateSinglePropertyDetails(propertyKey, propertyHelper);
                propertyEntries.Add(propertyEntry);
            }

            return(propertyEntries.ToArray());
        }
Example #17
0
        public void CreateBindingDetails_OverrideBehaviorOnClass_OverrideWithNever()
        {
            // Arrange
            var propertyAttributes = new object[]
            {
                new BindNeverAttribute(),
            };

            var context = new BindingMetadataProviderContext(
                ModelMetadataIdentity.ForProperty(typeof(BindRequiredOnClass).GetProperty(nameof(BindRequiredOnClass.Property)), typeof(int), typeof(BindRequiredOnClass)),
                new ModelAttributes(new object[0], propertyAttributes, null));

            var provider = new DefaultBindingMetadataProvider();

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.False(context.BindingMetadata.IsBindingAllowed);
            Assert.False(context.BindingMetadata.IsBindingRequired);
        }
Example #18
0
        public void CreateBindingDetails_FindsBindRequired_OnProperty()
        {
            // Arrange
            var propertyAttributes = new object[]
            {
                new BindRequiredAttribute(),
            };

            var context = new BindingMetadataProviderContext(
                ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
                new ModelAttributes(new object[0], propertyAttributes, null));

            var provider = new DefaultBindingMetadataProvider();

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.True(context.BindingMetadata.IsBindingAllowed);
            Assert.True(context.BindingMetadata.IsBindingRequired);
        }
Example #19
0
        public void CreateBindingDetails_OverrideInheritedBehaviorOnClass_OverrideWithRequired()
        {
            // Arrange
            var propertyAttributes = new object[]
            {
                new BindRequiredAttribute()
            };

            var context = new BindingMetadataProviderContext(
                ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(InheritedBindNeverOnClass)),
                new ModelAttributes(new object[0], propertyAttributes, null));

            var provider = new DefaultBindingMetadataProvider();

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.True(context.BindingMetadata.IsBindingAllowed);
            Assert.True(context.BindingMetadata.IsBindingRequired);
        }
Example #20
0
        public void CreateBindingDetails_FindsBindingBehaviorNever_OnProperty()
        {
            // Arrange
            var propertyAttributes = new object[]
            {
                new BindingBehaviorAttribute(BindingBehavior.Never),
            };

            var context = new BindingMetadataProviderContext(
                ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)),
                new ModelAttributes(new object[0], propertyAttributes, null));

            var provider = new DefaultBindingMetadataProvider();

            // Act
            provider.CreateBindingMetadata(context);

            // Assert
            Assert.False(context.BindingMetadata.IsBindingAllowed);
            Assert.False(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 DefaultMetadataDetails(
                                               ModelMetadataIdentity.ForProperty(typeof(int), originalName, 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(expectedNames.Count(), properties.Count);
            Assert.Equal(expectedNames.ToArray(), properties.Select(p => p.PropertyName).ToArray());
        }
 private ModelMetadataCacheEntry GetCacheEntry(PropertyInfo property, Type modelType)
 {
     return(_modelMetadataCache.GetOrAdd(
                ModelMetadataIdentity.ForProperty(property, modelType, property.DeclaringType),
                _cacheEntryFactory));
 }