Exemple #1
0
            public CompareAttributeWrapper(DataAnnotationsCompareAttribute attribute, ModelMetadata metadata)
                : base(attribute.OtherProperty)
            {
                _otherPropertyDisplayName = attribute.OtherPropertyDisplayName;

                if (_otherPropertyDisplayName is null &&
                    metadata.ContainerType != null)
                {
                    _otherPropertyDisplayName = ModelMetadataProviders.Current.GetMetadataForProperty(() => metadata.Model, metadata.ContainerType, attribute.OtherProperty).GetDisplayName();
                }

                if (_otherPropertyDisplayName is null)
                {
                    _otherPropertyDisplayName = attribute.OtherProperty;
                }

                // Copy settable properties from wrapped attribute. Don't reset default message accessor (set as
                // CompareAttribute constructor calls ValidationAttribute constructor) when all properties are null to
                // preserve default error message. Reset the message accessor when just ErrorMessageResourceType is
                // non-null to ensure correct InvalidOperationException.

                if (!String.IsNullOrEmpty(attribute.ErrorMessage) ||
                    !String.IsNullOrEmpty(attribute.ErrorMessageResourceName) ||
                    attribute.ErrorMessageResourceType != null)
                {
                    this.ErrorMessage             = attribute.ErrorMessage;
                    this.ErrorMessageResourceName = attribute.ErrorMessageResourceName;
                    this.ErrorMessageResourceType = attribute.ErrorMessageResourceType;
                }
            }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesDisplayName()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyDisplayNameModel), "MyProperty");

            var attribute = new CompareAttribute("OtherProperty");
            var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);

            var serviceCollection = new ServiceCollection();
            var requestServices = serviceCollection.BuildServiceProvider();

            var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);

            // Act
            var rules = adapter.GetClientValidationRules(context);

            // Assert
            var rule = Assert.Single(rules);
            // Mono issue - https://github.com/aspnet/External/issues/19
            Assert.Equal(
                PlatformNormalizer.NormalizeContent(
                    "'MyPropertyDisplayName' and 'OtherPropertyDisplayName' do not match."),
                rule.ErrorMessage);
        }
        public static void Constructor(string otherProperty)
        {
            CompareAttribute attribute = new CompareAttribute(otherProperty);
            Assert.Equal(otherProperty, attribute.OtherProperty);

            Assert.True(attribute.RequiresValidationContext);
        }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesDisplayName()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyDisplayNameModel), "MyProperty");

            var attribute = new CompareAttribute("OtherProperty");
            attribute.ErrorMessage = "CompareAttributeErrorMessage";

            var stringLocalizer = new Mock<IStringLocalizer>();
            var expectedProperties = new object[] { "MyPropertyDisplayName", "OtherPropertyDisplayName" };

            var expectedMessage = "'MyPropertyDisplayName' and 'OtherPropertyDisplayName' do not match.";

            stringLocalizer.Setup(s => s[attribute.ErrorMessage, expectedProperties])
                .Returns(new LocalizedString(attribute.ErrorMessage, expectedMessage));

            var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: stringLocalizer.Object);

            var actionContext = new ActionContext();
            var context = new ClientModelValidationContext(actionContext, metadata, metadataProvider);

            // Act
            var rules = adapter.GetClientValidationRules(context);

            // Assert
            var rule = Assert.Single(rules);
            // Mono issue - https://github.com/aspnet/External/issues/19
            Assert.Equal(expectedMessage, rule.ErrorMessage);
        }
        public void AddValidation_DoesNotTrounceExistingAttributes()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyNameModel), "MyProperty");

            var attribute = new CompareAttribute("OtherProperty");
            var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);

            var actionContext = new ActionContext();
            var context = new ClientModelValidationContext(
                actionContext,
                metadata,
                metadataProvider,
                new AttributeDictionary());

            context.Attributes.Add("data-val", "original");
            context.Attributes.Add("data-val-equalto", "original");
            context.Attributes.Add("data-val-equalto-other", "original");

            // Act
            adapter.AddValidation(context);

            // Assert
            Assert.Collection(
                context.Attributes,
                kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("original", kvp.Value); },
                kvp => { Assert.Equal("data-val-equalto", kvp.Key); Assert.Equal("original", kvp.Value); },
                kvp => { Assert.Equal("data-val-equalto-other", kvp.Key); Assert.Equal("original", kvp.Value); });
        }
        public void ValidateDoesNotThrowWhenComparedObjectsAreEqual() {
            object otherObject = new CompareObject("test");
            CompareObject currentObject = new CompareObject("test");
            ValidationContext testContext = new ValidationContext(otherObject, null, null);

            CompareAttribute attr = new CompareAttribute("CompareProperty");
            attr.Validate(currentObject.CompareProperty, testContext);
        }
        public static void Validate_does_not_throw_when_compared_objects_are_equal()
        {
            var otherObject = new CompareObject("test");
            var currentObject = new CompareObject("test");
            var testContext = new ValidationContext(otherObject, null, null);

            var attribute = new CompareAttribute("CompareProperty");
            AssertEx.DoesNotThrow(() => attribute.Validate(currentObject.CompareProperty, testContext));
        }
        public static void Validate_EqualObjects_DoesNotThrow()
        {
            var otherObject = new CompareObject("test");
            var currentObject = new CompareObject("test");
            var testContext = new ValidationContext(otherObject, null, null);

            var attribute = new CompareAttribute("CompareProperty");
            attribute.Validate(currentObject.CompareProperty, testContext);
        }
        public static void Validate_Invalid_Throws(string otherProperty, ValidationContext context, string otherPropertyDisplayName, Type exceptionType)
        {
            var attribute = new CompareAttribute(otherProperty);
            
            Assert.Throws(exceptionType, () => attribute.Validate("b", context));
            Assert.Equal(otherPropertyDisplayName, attribute.OtherPropertyDisplayName);

            // Make sure that we can run Validate twice
            Assert.Throws(exceptionType, () => attribute.Validate("b", context));
            Assert.Equal(otherPropertyDisplayName, attribute.OtherPropertyDisplayName);
        }
        public static void Validate_throws_with_OtherProperty_DisplayName()
        {
            var currentObject = new CompareObject("a");
            var otherObject = new CompareObject("b");

            var testContext = new ValidationContext(otherObject, null, null);
            testContext.DisplayName = "CurrentProperty";

            var attribute = new CompareAttribute("ComparePropertyWithDisplayName");
            Assert.Throws<ValidationException>(
                () => attribute.Validate(currentObject.CompareProperty, testContext));
        }
        public void ValidateThrowsWithOtherPropertyDisplayName()
        {
            CompareObject currentObject = new CompareObject("a");
            object otherObject = new CompareObject("b");

            ValidationContext testContext = new ValidationContext(otherObject, null, null);
            testContext.DisplayName = "CurrentProperty";

            CompareAttribute attr = new CompareAttribute("ComparePropertyWithDisplayName");
            Assert.Throws<ValidationException>(
                delegate { attr.Validate(currentObject.CompareProperty, testContext); }, "'CurrentProperty' and 'DisplayName' do not match.");
        }
        public static void Validate_throws_when_PropertyName_is_unknown()
        {
            var currentObject = new CompareObject("a");
            var otherObject = new CompareObject("b");

            var testContext = new ValidationContext(otherObject, null, null);
            testContext.DisplayName = "CurrentProperty";

            var attribute = new CompareAttribute("UnknownPropertyName");
            Assert.Throws<ValidationException>(
                () => attribute.Validate(currentObject.CompareProperty, testContext));
            // cannot check error message - not defined on ret builds
        }
        public void ValidateThrowsWhenComparedObjectsAreNotEqual() {
            CompareObject currentObject = new CompareObject("a");
            object otherObject = new CompareObject("b");

            ValidationContext testContext = new ValidationContext(otherObject, null, null);
            testContext.DisplayName = "CurrentProperty";

            CompareAttribute attr = new CompareAttribute("CompareProperty");
            ExceptionHelper.ExpectException<System.ComponentModel.DataAnnotations.ValidationException>(
                delegate {
                    attr.Validate(currentObject.CompareProperty, testContext);
                }, "'CurrentProperty' and 'CompareProperty' do not match.");
        }
        public void ValidateThrowsWhenPropertyNameIsUnknown() {
            CompareObject currentObject = new CompareObject("a");
            object otherObject = new CompareObject("b");

            ValidationContext testContext = new ValidationContext(otherObject, null, null);
            testContext.DisplayName = "CurrentProperty";

            CompareAttribute attr = new CompareAttribute("UnknownPropertyName");
            ExceptionHelper.ExpectException<System.ComponentModel.DataAnnotations.ValidationException>(
                () => attr.Validate(currentObject.CompareProperty, testContext),
                "Could not find a property named UnknownPropertyName."
            );
        }
        public static void Validate_PropertyHasDisplayName_UpdatesFormatErrorMessageToContainDisplayName()
        {
            CompareAttribute attribute = new CompareAttribute(nameof(CompareObject.ComparePropertyWithDisplayName));

            string oldErrorMessage = attribute.FormatErrorMessage("name");
            Assert.False(oldErrorMessage.Contains("CustomDisplayName"));

            Assert.Throws<ValidationException>(() => attribute.Validate("test1", new ValidationContext(new CompareObject("test"))));

            string newErrorMessage = attribute.FormatErrorMessage("name");
            Assert.NotEqual(oldErrorMessage, newErrorMessage);
            Assert.True(newErrorMessage.Contains("CustomDisplayName"));
        }
        private ValidationAttribute CopyAttribute(ValidationAttribute attribute)
        {
            ValidationAttribute result = null;

            if (attribute is RangeAttribute)
            {
                var attr = (RangeAttribute)attribute;
                result = (attr.Minimum is double)
                                        ?  new RangeAttribute((double)attr.Minimum, (double)attr.Maximum)
                                        :  new RangeAttribute((int)attr.Minimum, (int)attr.Maximum);
            }

            if (attribute is RegularExpressionAttribute)
            {
                var attr = (RegularExpressionAttribute)attribute;
                result = new RegularExpressionAttribute(attr.Pattern);
            }

            if (attribute is RequiredAttribute)
            {
                result = new RequiredAttribute();
            }

            if (attribute is StringLengthAttribute)
            {
                var attr = (StringLengthAttribute)attribute;
                result = new StringLengthAttribute(attr.MaximumLength)
                {
                    MinimumLength = attr.MinimumLength
                };
            }

            if (attribute is DA.CompareAttribute)
            {
                var attr = (DA.CompareAttribute)attribute;
                result = new DA.CompareAttribute(attr.OtherProperty);
            }

            if (attribute is DataTypeAttribute)
            {
                var attr = (DataTypeAttribute)attribute;
                result = new DataTypeAttribute(attr.DataType);
            }

            if (result == null && attribute.GetType().GetInterfaces().Contains(typeof(ICloneable)))
            {
                result = ((ICloneable)attribute).Clone() as ValidationAttribute;
            }

            return(result);
        }
Exemple #17
0
        public static void Validate_PropertyHasDisplayName_UpdatesFormatErrorMessageToContainDisplayName()
        {
            CompareAttribute attribute = new CompareAttribute(nameof(CompareObject.ComparePropertyWithDisplayName));

            string oldErrorMessage = attribute.FormatErrorMessage("name");

            Assert.False(oldErrorMessage.Contains("CustomDisplayName"));

            Assert.Throws <ValidationException>(() => attribute.Validate("test1", new ValidationContext(new CompareObject("test"))));

            string newErrorMessage = attribute.FormatErrorMessage("name");

            Assert.NotEqual(oldErrorMessage, newErrorMessage);
            Assert.True(newErrorMessage.Contains("CustomDisplayName"));
        }
        public static void Validate_throws_when_PropertyName_is_unknown()
        {
            var currentObject = new CompareObject("a");
            var otherObject   = new CompareObject("b");

            var testContext = new ValidationContext(otherObject, null, null);

            testContext.DisplayName = "CurrentProperty";

            var attribute = new CompareAttribute("UnknownPropertyName");

            Assert.Throws <ValidationException>(
                () => attribute.Validate(currentObject.CompareProperty, testContext));
            // cannot check error message - not defined on ret builds
        }
Exemple #19
0
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesPropertyName()
        {
            // Arrange
            var metadataProvider = new DataAnnotationsModelMetadataProvider();
            var metadata = metadataProvider.GetMetadataForProperty(() => null, typeof(PropertyNameModel), "MyProperty");
            var attribute = new CompareAttribute("OtherProperty");
            var context = new ClientModelValidationContext(metadata, metadataProvider);
            var adapter = new CompareAttributeAdapter(attribute);

            // Act
            var rules = adapter.GetClientValidationRules(context);

            // Assert
            var rule = Assert.Single(rules);
            Assert.Equal("'MyProperty' and 'OtherProperty' do not match.", rule.ErrorMessage);
        }
        public void GetClientValidationRulesReturnsModelClientValidationEqualToRule() {

            Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
            Mock<ModelMetadata> metadata = new Mock<ModelMetadata>(provider.Object, null, null, typeof(string), null);
            metadata.Setup(m => m.DisplayName).Returns("CurrentProperty");

            CompareAttribute attr = new CompareAttribute("CompareProperty");
            List<ModelClientValidationRule> ruleList = new List<ModelClientValidationRule>(attr.GetClientValidationRules(metadata.Object, null));

            Assert.AreEqual(ruleList.Count, 1);

            ModelClientValidationEqualToRule actualRule = ruleList[0] as ModelClientValidationEqualToRule;

            Assert.AreEqual(actualRule.ErrorMessage, "'CurrentProperty' and 'CompareProperty' do not match.", "*.CompareProperty");
            Assert.AreEqual(actualRule.ValidationType, "equalto");
            Assert.AreEqual(actualRule.ValidationParameters["other"], "*.CompareProperty");
        }
Exemple #21
0
        public static MvcHtmlString PassFor <TModel, TValue>(this HtmlHelper <TModel> html, Expression <Func <TModel, TValue> > expression, IDictionary <string, object> htmlAttributes = null, bool readOnly = false)
        {
            if (htmlAttributes == null)
            {
                htmlAttributes = new Dictionary <string, object>();
            }
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

            htmlAttributes.Add("placeholder", modelMetadata.DisplayName);
            htmlAttributes.Add("class", "form-control");
            htmlAttributes.Add("type", "password");
            if ((readOnly || modelMetadata.IsReadOnly) && !htmlAttributes.ContainsKey("readonly"))
            {
                htmlAttributes.Add("readonly", "readonly");
            }
            MemberExpression body = expression.Body as MemberExpression;

            if (body != null)
            {
                MaxLengthAttribute maxLengthAttribute = (body.Member.GetCustomAttributes(typeof(MaxLengthAttribute), false)).FirstOrDefault() as MaxLengthAttribute;
                if (maxLengthAttribute != null && !htmlAttributes.ContainsKey("maxlength"))
                {
                    htmlAttributes.Add("data-rule-maxlength", maxLengthAttribute.Length);
                }
                MinLengthAttribute minLengthAttribute = (body.Member.GetCustomAttributes(typeof(MinLengthAttribute), false)).FirstOrDefault() as MinLengthAttribute;
                if (minLengthAttribute != null && !htmlAttributes.ContainsKey("minlength"))
                {
                    htmlAttributes.Add("data-rule-minlength", minLengthAttribute.Length);
                }
                RequiredAttribute requiredAttribute = (body.Member.GetCustomAttributes(typeof(RequiredAttribute), false)).FirstOrDefault() as RequiredAttribute;
                if (requiredAttribute != null)
                {
                    htmlAttributes.Add("required", true);
                }
                System.ComponentModel.DataAnnotations.CompareAttribute compare =
                    (body.Member.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.CompareAttribute), false))
                    .FirstOrDefault() as System.ComponentModel.DataAnnotations.CompareAttribute;
                if (compare != null)
                {
                    htmlAttributes.Add("data-rule-equalTo", "#" + compare.OtherProperty);
                }
            }
            htmlAttributes.Add("autocomplete", "off");
            return(InputExtensions.TextBoxFor(html, expression, htmlAttributes));
        }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesPropertyName()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyNameModel), "MyProperty");
            var attribute = new CompareAttribute("OtherProperty");
            var serviceCollection = new ServiceCollection();
            var requestServices = serviceCollection.BuildServiceProvider();
            var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
            var adapter = new CompareAttributeAdapter(attribute);

            // Act
            var rules = adapter.GetClientValidationRules(context);

            // Assert
            var rule = Assert.Single(rules);
            Assert.Equal("'MyProperty' and 'OtherProperty' do not match.", rule.ErrorMessage);
        }
Exemple #23
0
		public void GetValidationResult ()
		{
			var sla = new CompareAttribute ("B");
			var obj = new TestModel { A = "x", B = "x" };
			var ctx = new ValidationContext(obj, null, null);

			Assert.IsNotNull (sla.GetValidationResult (null, ctx), "#A1-1");
			Assert.IsNotNull (sla.GetValidationResult (String.Empty, ctx), "#A1-2");
			Assert.IsNotNull (sla.GetValidationResult (obj, ctx), "#A1-3");
			Assert.IsNull (sla.GetValidationResult (obj.A, ctx), "#A1-4");

			obj = new TestModel { A = "x", B = "n" };

			Assert.IsNotNull (sla.GetValidationResult (null, ctx), "#B-1");
			Assert.IsNotNull (sla.GetValidationResult (obj, ctx), "#B-2");
			Assert.IsNotNull (sla.GetValidationResult (true, ctx), "#B-3");
			Assert.IsNotNull (sla.GetValidationResult (DateTime.Now, ctx), "#B-4");
		}
Exemple #24
0
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesResourceOverride()
        {
            // Arrange
            var metadataProvider = new DataAnnotationsModelMetadataProvider();
            var metadata = metadataProvider.GetMetadataForProperty(() => null, typeof(PropertyNameModel), "MyProperty");
            var attribute = new CompareAttribute("OtherProperty")
            {
                ErrorMessageResourceName = "CompareAttributeTestResource",
                ErrorMessageResourceType = typeof(Test.Resources),
            };
            var context = new ClientModelValidationContext(metadata, metadataProvider);
            var adapter = new CompareAttributeAdapter(attribute);

            // Act
            var rules = adapter.GetClientValidationRules(context);

            // Assert
            var rule = Assert.Single(rules);
            Assert.Equal("Comparing MyProperty to OtherProperty.", rule.ErrorMessage);
        }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesOverride()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty( typeof(PropertyNameModel), "MyProperty");
            var attribute = new CompareAttribute("OtherProperty")
            {
                ErrorMessage = "Hello '{0}', goodbye '{1}'."
            };
            var serviceCollection = new ServiceCollection();
            var requestServices = serviceCollection.BuildServiceProvider();
            var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
            var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);

            // Act
            var rules = adapter.GetClientValidationRules(context);

            // Assert
            var rule = Assert.Single(rules);
            Assert.Equal("Hello 'MyProperty', goodbye 'OtherProperty'.", rule.ErrorMessage);
        }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesDisplayName()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyDisplayNameModel), "MyProperty");

            var attribute = new CompareAttribute("OtherProperty");
            attribute.ErrorMessage = "CompareAttributeErrorMessage";

            var stringLocalizer = new Mock<IStringLocalizer>();
            var expectedProperties = new object[] { "MyPropertyDisplayName", "OtherPropertyDisplayName" };

            var expectedMessage = "'MyPropertyDisplayName' and 'OtherPropertyDisplayName' do not match.";

            stringLocalizer.Setup(s => s[attribute.ErrorMessage, expectedProperties])
                .Returns(new LocalizedString(attribute.ErrorMessage, expectedMessage));

            var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: stringLocalizer.Object);

            var actionContext = new ActionContext();
            var context = new ClientModelValidationContext(
                actionContext,
                metadata,
                metadataProvider,
                new AttributeDictionary());

            // Act
            adapter.AddValidation(context);

            // Assert
            Assert.Collection(
                context.Attributes,
                kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); },
                kvp => { Assert.Equal("data-val-equalto", kvp.Key); Assert.Equal(expectedMessage, kvp.Value); },
                kvp =>
                {
                    Assert.Equal("data-val-equalto-other", kvp.Key);
                    Assert.Equal(kvp.Value, "*.OtherProperty");
                });
        }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesResourceOverride()
        {
            if (TestPlatformHelper.IsMono)
            {
                // ValidationAttribute in Mono does not read non-public resx properties.
                return;
            }

            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyNameModel), "MyProperty");
            var attribute = new CompareAttribute("OtherProperty")
            {
                ErrorMessageResourceName = "CompareAttributeTestResource",
                ErrorMessageResourceType = typeof(Extensions.Test.Resources),
            };
            var serviceCollection = new ServiceCollection();
            var requestServices = serviceCollection.BuildServiceProvider();
            var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
            var adapter = new CompareAttributeAdapter(attribute);

            // Act
            var rules = adapter.GetClientValidationRules(context);

            // Assert
            var rule = Assert.Single(rules);
            Assert.Equal("Comparing MyProperty to OtherProperty.", rule.ErrorMessage);
        }
Exemple #28
0
        private static TagBuilder TextBoxTagFor <TModel, TValue>(this HtmlHelper <TModel> html, Expression <Func <TModel, TValue> > expression, bool readOnly = false, bool required = false)
        {
            TagBuilder       tag  = null;
            ModelMetadata    meta = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
            MemberExpression body = expression.Body as MemberExpression;

            if (body != null)
            {
                RequiredAttribute requiredAttribute = (body.Member.GetCustomAttributes(typeof(RequiredAttribute), false)).FirstOrDefault() as RequiredAttribute;
                required = required || requiredAttribute != null;

                var value = GetModelValue(meta);

                tag = TextBoxTag(html, meta.DisplayName, meta.PropertyName, meta.PropertyName,
                                 new ViewModels.FieldProperties {
                    ReadOnly = readOnly, Required = required, Value = value
                });

                MaxLengthAttribute maxLengthAttribute = (body.Member.GetCustomAttributes(typeof(MaxLengthAttribute), false)).FirstOrDefault() as MaxLengthAttribute;
                if (maxLengthAttribute != null)
                {
                    tag.Attributes.Add("data-rule-maxlength", maxLengthAttribute.Length.ToString());
                }

                MinLengthAttribute minLengthAttribute = (body.Member.GetCustomAttributes(typeof(MinLengthAttribute), false)).FirstOrDefault() as MinLengthAttribute;
                if (minLengthAttribute != null)
                {
                    tag.Attributes.Add("data-rule-minlength", minLengthAttribute.Length.ToString());
                }

                RangeAttribute rangeAttribute = (body.Member.GetCustomAttributes(typeof(RangeAttribute), false)).FirstOrDefault() as RangeAttribute;
                if (rangeAttribute != null)
                {
                    tag.Attributes.Add("data-rule-range", "[" + rangeAttribute.Minimum + "," + rangeAttribute.Maximum + "]");
                }

                EmailAddressAttribute email = (body.Member.GetCustomAttributes(typeof(EmailAddressAttribute), false)).FirstOrDefault() as EmailAddressAttribute;
                if (email != null)
                {
                    tag.Attributes.Add("data-rule-email", "true");
                }

                UrlAttribute url = (body.Member.GetCustomAttributes(typeof(UrlAttribute), false)).FirstOrDefault() as UrlAttribute;
                if (url != null)
                {
                    tag.Attributes.Add("data-rule-url", "true");
                }

                System.ComponentModel.DataAnnotations.CompareAttribute compare =
                    (body.Member.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.CompareAttribute), false))
                    .FirstOrDefault() as System.ComponentModel.DataAnnotations.CompareAttribute;
                if (compare != null)
                {
                    tag.Attributes.Add("data-rule-equalTo", "#" + compare.OtherProperty.ToLower());
                }


                var type = meta.ModelType;
                if (type == typeof(int) || type == typeof(float) || type == typeof(long) || type == typeof(byte) ||
                    type == typeof(short) || type == typeof(decimal) || type == typeof(double) ||
                    type == typeof(int?) || type == typeof(float?) || type == typeof(long?) || type == typeof(byte?) ||
                    type == typeof(short?) || type == typeof(decimal?) || type == typeof(double?))
                {
                    if (!tag.Attributes.ContainsKey("value"))
                    {
                        tag.Attributes.Add("value", "");
                    }
                    tag.Attributes.Add("data-rule-number", "true");
                }
            }
            return(tag);
        }
        private ValidationAttribute CopyAttribute(ValidationAttribute attribute)
        {
            ValidationAttribute result = null;

            if (attribute is RangeAttribute)
            {
                var attr = (RangeAttribute)attribute;
                result = (attr.Minimum is double)
                    ?  new RangeAttribute((double)attr.Minimum, (double)attr.Maximum)
                    :  new RangeAttribute((int)attr.Minimum, (int)attr.Maximum);
            }

            if (attribute is RegularExpressionAttribute)
            {
                var attr = (RegularExpressionAttribute)attribute;
                result = new RegularExpressionAttribute(attr.Pattern);
            }

            if (attribute is RequiredAttribute)
                result = new RequiredAttribute();

            if (attribute is StringLengthAttribute)
            {
                var attr = (StringLengthAttribute)attribute;
                result = new StringLengthAttribute(attr.MaximumLength)
                {
                    MinimumLength = attr.MinimumLength
                };
            }

            if (attribute is DA.CompareAttribute)
            {
                var attr = (DA.CompareAttribute)attribute;
                result = new DA.CompareAttribute(attr.OtherProperty);
            }

            if (attribute is DataTypeAttribute)
            {
                var attr = (DataTypeAttribute)attribute;
                result = new DataTypeAttribute(attr.DataType);
            }

            if (result == null && attribute.GetType().GetInterfaces().Contains(typeof(ICloneable)))
                result = ((ICloneable)attribute).Clone() as ValidationAttribute;

            return result;
        }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesPropertyName()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyNameModel), "MyProperty");

            var attribute = new CompareAttribute("OtherProperty");
            var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);

            // Mono issue - https://github.com/aspnet/External/issues/19
            var expectedMessage = PlatformNormalizer.NormalizeContent("'MyProperty' and 'OtherProperty' do not match.");

            var actionContext = new ActionContext();
            var context = new ClientModelValidationContext(
                actionContext,
                metadata,
                metadataProvider,
                new AttributeDictionary());

            // Act
            adapter.AddValidation(context);

            // Assert
            Assert.Collection(
                context.Attributes,
                kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); },
                kvp => { Assert.Equal("data-val-equalto", kvp.Key); Assert.Equal(expectedMessage, kvp.Value); },
                kvp =>
                {
                    Assert.Equal("data-val-equalto-other", kvp.Key);
                    Assert.Equal(kvp.Value, "*.OtherProperty");
                });
        }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesResourceOverride()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyNameModel), "MyProperty");

            var attribute = new CompareAttribute("OtherProperty")
            {
                ErrorMessageResourceName = "CompareAttributeTestResource",
                ErrorMessageResourceType = typeof(DataAnnotations.Test.Resources),
            };
            var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);

            var expectedMessage = "Comparing MyProperty to OtherProperty.";

            var actionContext = new ActionContext();
            var context = new ClientModelValidationContext(
                actionContext,
                metadata,
                metadataProvider,
                new AttributeDictionary());

            // Act
            adapter.AddValidation(context);

            // Assert
            Assert.Collection(
                context.Attributes,
                kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); },
                kvp => { Assert.Equal("data-val-equalto", kvp.Key); Assert.Equal(expectedMessage, kvp.Value); },
                kvp =>
                {
                    Assert.Equal("data-val-equalto-other", kvp.Key);
                    Assert.Equal(kvp.Value, "*.OtherProperty");
                });
        }
        public void ValidateThrowsWhenPropertyNameIsUnknown()
        {
            CompareObject currentObject = new CompareObject("a");
            object otherObject = new CompareObject("b");

            ValidationContext testContext = new ValidationContext(otherObject, null, null);
            testContext.DisplayName = "CurrentProperty";

            CompareAttribute attr = new CompareAttribute("UnknownPropertyName");
            Assert.Throws<ValidationException>(
                () => attr.Validate(currentObject.CompareProperty, testContext),
                "Could not find a property named UnknownPropertyName."
                );
        }
        public void ClientRulesWithCompareAttribute_ErrorMessageUsesResourceOverride()
        {
            // Arrange
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var metadata = metadataProvider.GetMetadataForProperty(typeof(PropertyNameModel), "MyProperty");
            var attribute = new CompareAttribute("OtherProperty")
            {
                ErrorMessageResourceName = "CompareAttributeTestResource",
                ErrorMessageResourceType = typeof(DataAnnotations.Test.Resources),
            };
            var serviceCollection = new ServiceCollection();
            var requestServices = serviceCollection.BuildServiceProvider();
            var context = new ClientModelValidationContext(metadata, metadataProvider, requestServices);
            var adapter = new CompareAttributeAdapter(attribute, stringLocalizer: null);

            // Act
            var rules = adapter.GetClientValidationRules(context);

            // Assert
            var rule = Assert.Single(rules);
            Assert.Equal("Comparing MyProperty to OtherProperty.", rule.ErrorMessage);
        }
        public void ModelClientValidationEqualToRuleUsesSetDisplayName()
        {
            Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
            ModelMetadata metadata = new ModelMetadata(provider.Object, typeof(CompareObject), null, typeof(string), null);
            metadata.DisplayName = "CurrentProperty";

            CompareAttribute attr = new CompareAttribute("ComparePropertyWithDisplayName");
            attr.OtherPropertyDisplayName = "SetDisplayName";

            List<ModelClientValidationRule> ruleList = new List<ModelClientValidationRule>(attr.GetClientValidationRules(metadata, null));
            Assert.Equal(ruleList.Count, 1);
            ModelClientValidationEqualToRule actualRule = ruleList[0] as ModelClientValidationEqualToRule;

            Assert.Equal("'CurrentProperty' and 'SetDisplayName' do not match.", actualRule.ErrorMessage);
        }