/// <summary>
        /// Merges the specified messages.
        /// </summary>
        /// <param name="validationSource">The validation source.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns>
        /// The merged message.
        /// </returns>
        public MergedValidationMessage Merge(IValidatable validationSource, string propertyName = null)
        {
            validationSource.CannotBeNull();

            ValidationMessageCollection messages = new ValidationMessageCollection();

            if (propertyName == null)
            {
                foreach (var validationMessage in this)
                {
                    if (validationMessage.ValidationSource == validationSource)
                    {
                        messages.Add(validationMessage);
                    }
                }
            }
            else
            {
                foreach (var validationMessage in this)
                {
                    if (validationMessage.ValidationSource == validationSource &&
                        validationMessage.PropertyName == propertyName)
                    {
                        messages.Add(validationMessage);
                    }
                }
            }

            return(Merge(messages));
        }
        /// <summary>
        /// Inserts avalidation message at the specified index.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="message">The message.</param>
        public new void Insert(int index, ValidationMessage message)
        {
            index.MustBeBetween(0, this.Count);
            message.CannotBeNull();

            ValidationMessageCollection messages = this[message.ValidationSource, message.PropertyName, message.ValidationContext];

            if (messages != null &&
                messages.Count > 0)
            {
                // insert only if there are no messages with higher validation level for this property
                if (!messages.Any(x => x.ValidationLevel > message.ValidationLevel))
                {
                    // remove messages with lower priority
                    foreach (var lowerPriorityMessage in messages.Where(x => x.ValidationLevel < message.ValidationLevel))
                    {
                        this.Remove(lowerPriorityMessage);
                    }

                    // insert message
                    base.Insert(Math.Min(this.Count, index), message);
                }
            }
            else
            {
                base.Insert(index, message);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ValidationException" /> class.
        /// </summary>
        /// <param name="validationMessages">The validation messages.</param>
        public ValidationException(ValidationMessageCollection validationMessages)
            : this()
        {
            validationMessages.CannotBeNull();

            this.ValidaitonMessages = validationMessages;
        }
예제 #4
0
        /// <summary>
        /// Validates the specified property of the specified validation source.
        /// </summary>
        /// <param name="validationSource">The validation source.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns>The collection of validation mesasges.</returns>
        public static ValidationMessageCollection Validate(this IValidatable validationSource, string propertyName)
        {
            validationSource.CannotBeNull();
            propertyName.CannotBeNullOrEmpty();

            ValidationMessageCollection messages = new ValidationMessageCollection();
            List <string> validationContexts;
            object        propertyValue;

            // get property value
            var properties = ReflectionExtensions.GetProperties(validationSource.GetType());

            if (properties.TryGetValue(propertyName, out PropertyData propertyData))
            {
                if (propertyData.PropertyInfo.CanRead &&
                    propertyData.PropertyInfo.CanWrite)
                {
                    propertyValue = propertyData.PropertyInfo.GetValue(validationSource);

                    // get validation context
                    validationContexts = new List <string>();
                    validationContexts.Add(ValidationContext.Default);                                                     // always add the default validation context
                    validationContexts.AddRange(validationSource.GetActiveValidationContexts() ?? Array.Empty <string>()); // add currently active validation context

                    foreach (var validationContext in validationContexts.Distinct())
                    {
                        messages.AddRange(validationSource.Validate(propertyName, propertyValue, validationContext));
                    }
                }
            }

            return(messages);
        }
예제 #5
0
        /// <summary>
        /// Validates the the specified validation source.
        /// </summary>
        /// <param name="validationSource">The validation source.</param>
        /// <returns>
        /// The collection of validation mesasges.
        /// </returns>
        public static ValidationMessageCollection Validate(this IValidatable validationSource)
        {
            validationSource.CannotBeNull();

            ValidationMessageCollection messages = new ValidationMessageCollection();
            var propertyNames = ReflectionExtensions.GetProperties(validationSource.GetType()).Keys;

            foreach (var propertyName in propertyNames)
            {
                messages.AddRange(validationSource.Validate(propertyName));
            }

            return(messages);
        }
        /// <summary>
        /// Merges the specified messages.
        /// </summary>
        /// <param name="list">The validation message list.</param>
        /// <returns>Merged message.</returns>
        private static MergedValidationMessage Merge(ValidationMessageCollection list)
        {
            ValidationLevel  validationLevel;
            int              validationPriortiy = int.MaxValue;
            HashSet <string> messages           = new HashSet <string>();

            if (list == null ||
                list.Count == 0)
            {
                validationLevel = ValidationLevel.None;
            }
            else if (list.Count == 1)
            {
                messages.Add(list[0].Message);
                validationLevel = list[0].ValidationLevel;
            }
            else
            {
                validationLevel = ValidationLevel.None;

                // find max validation level
                foreach (ValidationMessage vm in list)
                {
                    validationLevel = (int)vm.ValidationLevel > (int)validationLevel ? vm.ValidationLevel : validationLevel;
                }

                // find max validation priority
                foreach (ValidationMessage vm in list.Where(x => x.ValidationLevel == validationLevel))
                {
                    validationPriortiy = vm.ValidationPriority < validationPriortiy ? vm.ValidationPriority : validationPriortiy;
                }

                // select only messages for that level
                foreach (ValidationMessage vm in list.Where(x => x.ValidationLevel == validationLevel &&
                                                            x.ValidationPriority == validationPriortiy))
                {
                    if (!messages.Contains(vm.Message))
                    {
                        // prevent duplicates
                        messages.Add(vm.Message);
                    }
                }
            }

            return(new MergedValidationMessage(validationLevel, messages));
        }
예제 #7
0
        /// <summary>
        /// Validates the specified property of the specified validation source for the specified property value in specified validation context by using validation attributes.
        /// </summary>
        /// <param name="validationSource">The validation source.</param>
        /// <param name="propertyName">The property name.</param>
        /// <param name="propertyValue">The property value.</param>
        /// <param name="validationContext">The validation context.</param>
        /// <returns>
        /// The collection of validation mesasges.
        /// </returns>
        public static ValidationMessageCollection ValidateAttributes(this IValidatable validationSource, string propertyName, object propertyValue, string validationContext)
        {
            validationSource.CannotBeNull();
            propertyName.CannotBeNullOrEmpty();

            ValidationMessageCollection messages = new ValidationMessageCollection();
            var  validationAttributes            = ReflectionExtensions.GetProperties(validationSource.GetType())[propertyName].ValidationAttributes;
            bool isValid;

            // perform attribute based validation
            foreach (var validationAttribute in validationAttributes)
            {
                // only matching validation context gets validated
                if (validationAttribute.ValidationContext == validationContext)
                {
                    // custom validators might cause exceptions that are hard to find
                    try
                    {
                        isValid = validationAttribute.IsValid(propertyValue);
                    }
                    catch (Exception ex)
                    {
                        throw new ValidationErrorException("Unhandled validation exception occurred.", validationAttribute.GetType(), validationSource.GetType(), propertyName, ex);
                    }

                    if (!isValid)
                    {
                        var messageKey         = validationAttribute.MessageKey ?? validationAttribute.GetDefaultMessageKey() ?? "UndefinedMessageKey";
                        var message            = validationAttribute.Message ?? validationAttribute.GetDefaultMessage() ?? "Undefined message.";
                        var messageParameters  = validationAttribute.MessageParameters;
                        var validationLevel    = validationAttribute.ValidationLevel;
                        var validationPriority = validationAttribute.ValidationPriority;

                        // value is invalid -> add it to the list
                        messages.Add(new ValidationMessage(messageKey, message, messageParameters, validationSource, propertyName, validationLevel, validationContext, validationPriority));
                    }
                }
            }

            return(messages);
        }