Inheritance: ValidationAttribute, IClientValidatable
        /// <summary>
        /// Creates the validator.
        /// </summary>
        /// <param name="modelMetadata">The model metadata.</param>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        protected override ModelValidator CreateValidatorCore(ExtendedModelMetadata modelMetadata, ControllerContext context)
        {
            var attribute = new RequiredIfAttribute(OtherProperty, Operator, DependentValue);

            PopulateErrorMessage(attribute);
            return(new FoolproofValidator(modelMetadata, context, attribute));
        }
        public void verify_validators_caching()
        {
            const int testLoops     = 10;
            var       generatedCode = Enumerable.Repeat(0, 100).Select(x => "true")
                                      .Aggregate("true", (accumulator, item) => $"({accumulator} && {item} && !false)"); // give the parser some work (deep dive)

            var model             = new Model();
            var metadata          = GetModelMetadata(model, m => m.Value);
            var controllerContext = GetControllerContext();

            var assertThat = new AssertThatAttribute(generatedCode);
            var requiredIf = new RequiredIfAttribute(generatedCode);

            var nonCached = MeasureExecutionTime(() => new AssertThatValidator(metadata, controllerContext, assertThat));

            for (var i = 0; i < testLoops; i++)
            {
                var cached = MeasureExecutionTime(() => new AssertThatValidator(metadata, controllerContext, assertThat));
                Assert.True(nonCached > cached);
            }

            nonCached = MeasureExecutionTime(() => new RequiredIfValidator(metadata, controllerContext, requiredIf));
            for (var i = 0; i < testLoops; i++)
            {
                var cached = MeasureExecutionTime(() => new RequiredIfValidator(metadata, controllerContext, requiredIf));
                Assert.True(nonCached > cached);
            }
        }
        public void throw_when_no_httpcontext_is_available()
        {
            HttpContext.Current = null;

            var model           = new Model();
            var assertAttribute = new AssertThatAttribute("true");
            var requirAttribute = new RequiredIfAttribute("true");

            var metadata          = GetModelMetadata(model, m => m.Value);
            var controllerContext = GetControllerContext();

            var e = Assert.Throws <ValidationException>(() => new AssertThatValidator(metadata, controllerContext, assertAttribute).GetClientValidationRules().Single());

            Assert.Equal(
                "AssertThatValidator: collecting of client validation rules for Value field failed.",
                e.Message);
            Assert.IsType <ApplicationException>(e.InnerException);
            Assert.Equal(
                "HttpContext not available.",
                e.InnerException.Message);

            e = Assert.Throws <ValidationException>(() => new RequiredIfValidator(metadata, controllerContext, requirAttribute).GetClientValidationRules().Single());
            Assert.Equal(
                "RequiredIfValidator: collecting of client validation rules for Value field failed.",
                e.Message);
            Assert.IsType <ApplicationException>(e.InnerException);
            Assert.Equal(
                "HttpContext not available.",
                e.InnerException.Message);
        }
        private static void AssertErrorMessage(string input, string assertThatOutput, string requiredIfOutput)
        {
            var assertThat = new AssertThatAttribute("1!=1");
            var requiredIf = new RequiredIfAttribute("1==1");

            var isValid = typeof(ExpressiveAttribute).GetMethod("IsValid", BindingFlags.NonPublic | BindingFlags.Instance);
            var context = new ValidationContext(new MsgModel
            {
                Value1   = 0,
                Internal = new MsgModel
                {
                    Value1   = 1,
                    Internal = new MsgModel {
                        Value1 = 2
                    }
                }
            })
            {
                MemberName = "#{Value1}#"
            };

            if (input != null)
            {
                assertThat.ErrorMessage = requiredIf.ErrorMessage = input;
            }

            var assertThatResult = (ValidationResult)isValid.Invoke(assertThat, new[] { new object(), context });
            var requiredIfResult = (ValidationResult)isValid.Invoke(requiredIf, new[] { null, context });

            Assert.Equal(assertThatOutput, assertThatResult.ErrorMessage);
            Assert.Equal(requiredIfOutput, requiredIfResult.ErrorMessage);
        }
        public void throw_when_no_httpcontext_is_available()
        {
            HttpContext.Current = null;

            var model = new Model();
            var assertAttribute = new AssertThatAttribute("true");
            var requirAttribute = new RequiredIfAttribute("true");

            var metadata = GetModelMetadata(model, m => m.Value);
            var controllerContext = GetControllerContext();

            var e = Assert.Throws<ValidationException>(() => new AssertThatValidator(metadata, controllerContext, assertAttribute).GetClientValidationRules().Single());
            Assert.Equal(
                "AssertThatValidator: collecting of client validation rules for Value field failed.",
                e.Message);
            Assert.IsType<ApplicationException>(e.InnerException);
            Assert.Equal(
                "HttpContext not available.",
                e.InnerException.Message);

            e = Assert.Throws<ValidationException>(() => new RequiredIfValidator(metadata, controllerContext, requirAttribute).GetClientValidationRules().Single());
            Assert.Equal(
                "RequiredIfValidator: collecting of client validation rules for Value field failed.",
                e.Message);
            Assert.IsType<ApplicationException>(e.InnerException);
            Assert.Equal(
                "HttpContext not available.",
                e.InnerException.Message);
        }
Example #6
0
        public void Ctor_WithName()
        {
            var expected = "Name";
            var target   = new RequiredIfAttribute(expected);

            //Assert
            target.PropertyName.Should().Be(expected);
        }
Example #7
0
        public void ShallThrowIfValidationContextIsNull()
        {
            var attr = new RequiredIfAttribute("test", "value");

            Assert.Throws <ArgumentNullException>(() =>
            {
                attr.GetValidationResult("value", null);
            });
        }
Example #8
0
        public void SuccessfulValidationWithoutTargetedValue()
        {
            var model = new Mock {
                Property = "not the expected target"
            };
            var context = new ValidationContext(model);

            var attr = new RequiredIfAttribute("Property", "value");

            var result = attr.GetValidationResult("value", context);

            Assert.Equal(ValidationResult.Success, result);
        }
Example #9
0
        public void InvalidIfValueIsNull()
        {
            var model = new Mock {
                Property = "value"
            };
            var context = new ValidationContext(model);

            var attr = new RequiredIfAttribute("Property", "value");

            var result = attr.GetValidationResult(null, context);

            Assert.Equal("'Mock' is required because 'Property' has a value 'value'.", result.ErrorMessage);
        }
        public void throw_when_priority_is_not_provided_but_requested_explicitly()
        {
            var assertThat = new AssertThatAttribute("1!=1");
            var requiredIf = new RequiredIfAttribute("1==1");

            Assert.Null(assertThat.GetPriority());
            Assert.Null(requiredIf.GetPriority());

            var e = Assert.Throws <InvalidOperationException>(() => assertThat.Priority);

            Assert.Equal("The Priority property has not been set. Use the GetPriority method to get the value.", e.Message);
            e = Assert.Throws <InvalidOperationException>(() => requiredIf.Priority);
            Assert.Equal("The Priority property has not been set. Use the GetPriority method to get the value.", e.Message);
        }
        public void verify_attributes_equality()
        {
            var assertThat = new AssertThatAttribute("1 !=    1");
            var requiredIf = new RequiredIfAttribute("1 ==    1");

            var assertThat2 = new AssertThatAttribute("1    != 1");
            var requiredIf2 = new RequiredIfAttribute("1    == 1");

            Assert.True(assertThat.Equals(assertThat2));
            Assert.True(requiredIf.Equals(requiredIf2));

            Assert.False(assertThat.Equals(null));
            Assert.False(requiredIf.Equals(null));
        }
Example #12
0
        public void ShallThrowIfPropertyIsNotFound()
        {
            var model = new Mock {
                Property = null
            };
            var context = new ValidationContext(model);

            var attr = new RequiredIfAttribute("UnknownProperty", "value");

            Assert.Throws <ArgumentNullException>(() =>
            {
                attr.GetValidationResult("value", context);
            });
        }
Example #13
0
        public void RequiredIfAttribute_Test()
        {
            object passingValueBothPopulated = new { NewPassword = "******", Password = "******" };
            object failingValue = new { NewPassword = "******" };
            object passingValueNewPasswordNull = new { Password = "******" };
            object passingValueBothNull        = new { };

            RequiredIfAttribute attribute = new RequiredIfAttribute("Password", "NewPassword");

            //this does not test the model just the RequiredIfAttribute object's logic.
            Assert.IsTrue(attribute.IsValid(passingValueBothPopulated), "Assertion of positive case being true failed");
            Assert.IsFalse(attribute.IsValid(failingValue), "Assertion of negative case being false failed");
            Assert.IsTrue(attribute.IsValid(passingValueNewPasswordNull), "Assertion of positive case (Field  being false failed");
            Assert.IsTrue(attribute.IsValid(passingValueBothNull), "Assertion of negative case being false failed");
        }
        public void verify_attributes_identification()
        {
            var assertThat = new AssertThatAttribute("1 !=    1"); // spaces on purpose
            var requiredIf = new RequiredIfAttribute("1 ==    1");

            const string assertThatRepresentation = "ExpressiveAnnotations.Attributes.AssertThatAttribute[1!=1]";
            const string requiredIfRepresentation = "ExpressiveAnnotations.Attributes.RequiredIfAttribute[1==1]";

            Assert.Equal(assertThatRepresentation, assertThat.TypeId);
            Assert.Equal(requiredIfRepresentation, requiredIf.TypeId);

            Assert.Equal(assertThatRepresentation, assertThat.ToString());
            Assert.Equal(requiredIfRepresentation, requiredIf.ToString());

            Assert.Equal(assertThatRepresentation.GetHashCode(), assertThat.GetHashCode());
            Assert.Equal(requiredIfRepresentation.GetHashCode(), requiredIf.GetHashCode());
        }
        public void throw_when_requirement_is_applied_to_field_of_non_nullable_value_type()
        {
            var model           = new MisusedRequirementModel();
            var requirAttribute = new RequiredIfAttribute("true");

            var metadata          = GetModelMetadata(model, m => m.Value);
            var controllerContext = GetControllerContext();

            var e = Assert.Throws <ValidationException>(() => new RequiredIfValidator(metadata, controllerContext, requirAttribute));

            Assert.Equal(
                "RequiredIfValidator: validation applied to Value field failed.",
                e.Message);
            Assert.IsType <InvalidOperationException>(e.InnerException);
            Assert.Equal(
                "RequiredIfAttribute has no effect when applied to a field of non-nullable value type 'System.Int32'. Use nullable 'System.Int32?' version instead, or switch to AssertThatAttribute otherwise.",
                e.InnerException.Message);
        }
        public void verify_attributes_equality()
        {
            var assertThat = new AssertThatAttribute("1 !=    1");
            var requiredIf = new RequiredIfAttribute("1 ==    1");

            var assertThat2 = new AssertThatAttribute("1    != 1");
            var requiredIf2 = new RequiredIfAttribute("1    == 1");

            Assert.True(assertThat.Equals(assertThat2));
            Assert.True(requiredIf.Equals(requiredIf2));

            Assert.False(assertThat.Equals(null));
            Assert.False(requiredIf.Equals(null));
        }
        public void verify_validators_caching()
        {
            const int testLoops = 10;
            var generatedCode = Enumerable.Repeat(0, 100).Select(x => "true")
                .Aggregate("true", (accumulator, item) => $"({accumulator} && {item} && !false)"); // give the parser some work (deep dive)
            
            var model = new Model();
            var metadata = GetModelMetadata(model, m => m.Value);
            var controllerContext = GetControllerContext();

            var assertThat = new AssertThatAttribute(generatedCode);
            var requiredIf = new RequiredIfAttribute(generatedCode);

            var nonCached = MeasureExecutionTime(() => new AssertThatValidator(metadata, controllerContext, assertThat));
            for (var i = 0; i < testLoops; i++)
            {
                var cached = MeasureExecutionTime(() => new AssertThatValidator(metadata, controllerContext, assertThat));
                Assert.True(nonCached > cached);
            }

            nonCached = MeasureExecutionTime(() => new RequiredIfValidator(metadata, controllerContext, requiredIf));
            for (var i = 0; i < testLoops; i++)
            {
                var cached = MeasureExecutionTime(() => new RequiredIfValidator(metadata, controllerContext, requiredIf));
                Assert.True(nonCached > cached);
            }
        }
        private static void AssertErrorMessage(string input, string assertThatOutput, string requiredIfOutput)
        {
            var assertThat = new AssertThatAttribute("1!=1");
            var requiredIf = new RequiredIfAttribute("1==1");

            var isValid = typeof(ExpressiveAttribute).GetMethod("IsValid", BindingFlags.NonPublic | BindingFlags.Instance);
            var context = new ValidationContext(new MsgModel
            {
                Value1 = 0,
                Internal = new MsgModel
                {
                    Value1 = 1,
                    Internal = new MsgModel {Value1 = 2}
                }
            })
            {
                MemberName = "Value1"
            };

            if (input != null)
                assertThat.ErrorMessage = requiredIf.ErrorMessage = input;

            var assertThatResult = (ValidationResult) isValid.Invoke(assertThat, new[] {new object(), context});
            var requiredIfResult = (ValidationResult) isValid.Invoke(requiredIf, new[] {null, context});

            Assert.Equal(assertThatOutput, assertThatResult.ErrorMessage);
            Assert.Equal(requiredIfOutput, requiredIfResult.ErrorMessage);
        }
        public void throw_when_priority_is_not_provided_but_requested_explicitly()
        {
            var assertThat = new AssertThatAttribute("1!=1");
            var requiredIf = new RequiredIfAttribute("1==1");

            Assert.Null(assertThat.GetPriority());
            Assert.Null(requiredIf.GetPriority());

            var e = Assert.Throws<InvalidOperationException>(() => assertThat.Priority);
            Assert.Equal("The Priority property has not been set. Use the GetPriority method to get the value.", e.Message);
            e = Assert.Throws<InvalidOperationException>(() => requiredIf.Priority);
            Assert.Equal("The Priority property has not been set. Use the GetPriority method to get the value.", e.Message);
        }
        public void throw_when_requirement_is_applied_to_field_of_non_nullable_value_type()
        {
            var model = new MisusedRequirementModel();
            var requirAttribute = new RequiredIfAttribute("true");

            var metadata = GetModelMetadata(model, m => m.Value);
            var controllerContext = GetControllerContext();

            var e = Assert.Throws<ValidationException>(() => new RequiredIfValidator(metadata, controllerContext, requirAttribute));
            Assert.Equal(
                "RequiredIfValidator: validation applied to Value field failed.",
                e.Message);
            Assert.IsType<InvalidOperationException>(e.InnerException);
            Assert.Equal(
                "RequiredIfAttribute has no effect when applied to a field of non-nullable value type 'System.Int32'. Use nullable 'System.Int32?' version instead.",
                e.InnerException.Message);
        }
        public void verify_attributes_identification()
        {
            var assertThat = new AssertThatAttribute("1 !=    1"); // spaces on purpose
            var requiredIf = new RequiredIfAttribute("1 ==    1");

            const string assertThatRepresentation = "ExpressiveAnnotations.Attributes.AssertThatAttribute[1!=1]";
            const string requiredIfRepresentation = "ExpressiveAnnotations.Attributes.RequiredIfAttribute[1==1]";

            Assert.Equal(assertThatRepresentation, assertThat.TypeId);
            Assert.Equal(requiredIfRepresentation, requiredIf.TypeId);

            Assert.Equal(assertThatRepresentation, assertThat.ToString());
            Assert.Equal(requiredIfRepresentation, requiredIf.ToString());

            Assert.Equal(assertThatRepresentation.GetHashCode(), assertThat.GetHashCode());
            Assert.Equal(requiredIfRepresentation.GetHashCode(), requiredIf.GetHashCode());
        }