private List <string> DictionaryValidator(ValidationAttributes attribute, PropertyInfo propertyInfo)
        {
            List <string> errors = new List <string>();

            //get the property name and value
            string propertyName  = propertyInfo.Name;
            object propertyValue = propertyInfo.GetValue(this, null);

            if (!propertyValue.IsDictionary())
            {
                errors.Add($"The {propertyName} is not a valid Dictionary object.");
            }
            else
            {
                if (attribute.MinLength > 0)
                {
                    if (((ICollection)propertyValue).IsNull() || ((ICollection)propertyValue).Count < attribute.MinLength)
                    {
                        errors.Add($"The {propertyName} dictionary is empty.");
                    }
                }
            }

            return(errors);
        }
        private List <string> AlphaNumericValidator(ValidationAttributes attribute, PropertyInfo propertyInfo)
        {
            List <string> errors = new List <string>();

            //get the property name and value
            string propertyName  = propertyInfo.Name;
            string propertyValue = propertyInfo.GetValue(this, null).AsString().Trim();

            //null or empty check
            if (attribute.AllowNull == false && string.IsNullOrWhiteSpace(propertyValue))
            {
                errors.Add($"{propertyName} must not be null or empty.");
            }

            if (attribute.MinNumericValue != 0 || attribute.MaxNumericValue != 0)
            {
                if (propertyValue.IsDouble(true) || propertyValue.IsLong() || propertyValue.IsFloat(true) || propertyValue.IsInt())
                {
                    attribute.FieldFormat = ValidationAttributes.DataType.Numeric;
                    errors = NumericValidator(attribute, propertyInfo, true);
                }
                attribute.FieldFormat = ValidationAttributes.DataType.Alphanumeric;
            }

            //min length check
            if (attribute.MinLength > 0 && propertyValue?.Length < attribute.MinLength)
            {
                errors.Add($"{propertyName} must be at least {attribute.MinLength} characters.");
            }

            //max length check
            if (attribute.FieldLength > 0 && !string.IsNullOrWhiteSpace(propertyValue) && propertyValue.Length > attribute.FieldLength)
            {
                errors.Add($"{propertyName} must not exceed {attribute.FieldLength} characters.");
            }

            if (errors.Count == 0)
            {
                if (attribute.StringCase == ValidationAttributes.Case.Lower)
                {
                    propertyInfo.SetValue(this, propertyValue.ToLower());
                }
                else if (attribute.StringCase == ValidationAttributes.Case.Upper)
                {
                    propertyInfo.SetValue(this, propertyValue.ToUpper());
                }
                else
                {
                    propertyInfo.SetValue(this, propertyValue);
                }
            }

            return(errors);
        }
        private List <string> ObjectValidator(ValidationAttributes attribute, PropertyInfo propertyInfo)
        {
            List <string> errors = new List <string>();

            //get the property name and value
            string propertyName  = propertyInfo.Name;
            object propertyValue = propertyInfo.GetValue(this, null);

            if (!attribute.AllowNull && propertyValue.IsNull())
            {
                errors.Add($"The {propertyName} object is null.");
            }

            return(errors);
        }
        private List <string> DateTimeValidator(ValidationAttributes attribute, PropertyInfo propertyInfo)
        {
            List <string> errors = new List <string>();

            //get the property name and value
            string propertyName  = propertyInfo.Name;
            string propertyValue = propertyInfo.GetValue(this, null).AsString().Trim();

            if (propertyValue.IsNull() || !propertyValue.IsDateTime())
            {
                errors.Add($"{propertyName} is not a valid date/time string.");
            }

            return(errors);
        }
        private List <string> NumericValidator(ValidationAttributes attribute, PropertyInfo propertyInfo, bool allowCurrency = false)
        {
            List <string> errors = new List <string>();

            //get the property name and value
            string propertyName  = propertyInfo.Name;
            string propertyValue = propertyInfo.GetValue(this, null).AsString().Trim();

            //min length check
            if (attribute.MinLength > 0 && propertyValue?.Length < attribute.MinLength)
            {
                errors.Add($"{propertyName} must be at least {attribute.MinLength} characters.");
            }

            //too long check
            if (attribute.FieldLength > 0 && !string.IsNullOrWhiteSpace(propertyValue) &&
                propertyValue.AsDecimal().ToString(attribute.FormatString).Length > attribute.FieldLength)
            {
                errors.Add($"{propertyName} must not exceed {attribute.FieldLength} characters.");
            }

            //numeric value check
            if (propertyValue?.Length > 0 && !propertyValue.IsDecimal(allowCurrency))
            {
                errors.Add($"{propertyName} must be a numeric value.");
            }

            //numeric min value check
            if (propertyValue.IsDecimal() && !attribute.MinNumericValue.IsNull() && propertyValue.AsDecimal() < attribute.MinNumericValue)
            {
                errors.Add($"{propertyName} value must be equal to or greater than {attribute.MinNumericValue}.");
            }

            //numeric max value check
            if (propertyValue.IsDecimal() && attribute.MaxNumericValue > attribute.MinNumericValue && propertyValue.AsDecimal() > attribute.MaxNumericValue)
            {
                errors.Add($"{propertyName} value must be equal to or less than {attribute.MaxNumericValue}.");
            }

            return(errors);
        }
        /// <summary>
        /// This method validates model objects that use the Validation attribute class and provides formatting where a format string attribute was supplied.
        /// </summary>
        /// <returns>List of error strings</returns>
        private List <string> Validate()
        {
            List <string> _errors = new List <string>();

            PropertyInfo[] properties = this.GetType().GetProperties();

            foreach (PropertyInfo propertyInfo in properties)
            {
                string        value  = string.Empty;
                List <string> errors = null;

                IEnumerable <ValidationAttributes> attributes = (IEnumerable <ValidationAttributes>)propertyInfo.GetCustomAttributes(typeof(ValidationAttributes));
                if (attributes.Count() > 0)
                {
                    ValidationAttributes attribute = (ValidationAttributes)attributes.First();

                    if (!attribute.IsNull())
                    {
                        //get the data type
                        ValidationAttributes.DataType fieldFormat = attribute.FieldFormat;

                        //call the appropriate validation method
                        try
                        {
                            if (fieldFormat == ValidationAttributes.DataType.Numeric)
                            {
                                errors = NumericValidator(attribute, propertyInfo);
                            }
                            else if (fieldFormat == ValidationAttributes.DataType.Alphanumeric)
                            {
                                errors = AlphaNumericValidator(attribute, propertyInfo);
                            }
                            else if (fieldFormat == ValidationAttributes.DataType.DateTime)
                            {
                                errors = DateTimeValidator(attribute, propertyInfo);
                            }
                            else if (fieldFormat == ValidationAttributes.DataType.List)
                            {
                                errors = ListValidator(attribute, propertyInfo);
                            }
                            else if (fieldFormat == ValidationAttributes.DataType.Dictionary)
                            {
                                errors = DictionaryValidator(attribute, propertyInfo);
                            }
                            else if (fieldFormat == ValidationAttributes.DataType.Object)
                            {
                                errors = ObjectValidator(attribute, propertyInfo);
                            }

                            if (!errors.IsNull())
                            {
                                foreach (string error in errors)
                                {
                                    _errors.Add(error);
                                }
                                errors.Clear();
                                errors = null;
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception($"{propertyInfo.Name }: { ex.Message}");
                        }
                    }
                }
            }

            return(_errors.Count == 0 ? null : _errors);
        }