Ejemplo n.º 1
0
 /// <summary>
 /// Overridable method that lets a child rule return multiple validation messages for the <paramref name="entity"/>
 /// </summary>
 /// <param name="entity"></param>
 /// <returns></returns>
 public override IEnumerable<ValidationMessage> GetValidationMessages(object entity, RuleContext context)
 {
     object[] formatParams;
     if (context.Key == ExtensionName && !IsValid(entity, context, out formatParams))
     {
         yield return new ValidationMessage(this, formatParams);
     }
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Overridable method that lets a child rule return multiple validation messages for the <paramref name="entity"/>
 /// </summary>
 /// <param name="entity"></param>
 /// <returns></returns>
 public override IEnumerable<ValidationMessage> GetValidationMessages(object entity, RuleContext context)
 {
     object[] formatParams;
     // Only try to validate an object with this extension rule if the extension name matches the key
     if (context.Key == ExtensionName && !IsValid(entity, context, out formatParams))
     {
         yield return new ValidationMessage(this, formatParams);
     }
 }
        /// <summary>
        /// Recursively validates <paramref name="entity"/> by traversing all of its properties
        /// </summary>
        /// <param name="entity">The object to validate</param>
        /// <param name="parentContext">The rule context of the object that <paramref name="entity"/> belongs to</param>
        /// <param name="rules">The set of rules from the parent object to apply to <paramref name="entity"/></param>
        /// <param name="traverseProperties">Whether or not to traverse this <paramref name="entity"/>'s properties</param>
        /// <returns></returns>
        private IEnumerable<ValidationMessage> RecursiveValidate(object entity, RuleContext parentContext, IEnumerable<Rule> rules, bool traverseProperties = true)
        {
            var messages = Enumerable.Empty<ValidationMessage>();
            if (entity == null)
            {
                return messages;
            }

            // Ensure that the rules can be re-enumerated without re-evaluating the enumeration.
            var collectionRules = rules.ReEnumerable();

            var list = entity as IList;
            var dictionary = entity as IDictionary;
            if (traverseProperties && list != null)
            {
                // Recursively validate each list item and add the 
                // item index to the location of each validation message
                var listMessages = list.SelectMany((item, index)
                    => RecursiveValidate(item, parentContext.CreateChild(item, index), collectionRules).Select(each
                        => each.AppendToPath($"[{index}]")));
                messages = messages.Concat(listMessages);
            }

            else if (traverseProperties && dictionary != null)
            {
                // Dictionaries that don't provide any type info cannot be traversed, since it result in infinite iteration
                var shouldTraverseEntries = dictionary.IsTraversableDictionary();

                // Recursively validate each dictionary entry and add the entry 
                // key to the location of each validation message
                var dictMessages = dictionary.SelectMany((key, value)
                    => RecursiveValidate(value, parentContext.CreateChild(value, (string)key), collectionRules, shouldTraverseEntries).Select(each
                        => each.AppendToPath((string)key)));
                messages = messages.Concat(dictMessages);
            }

            // If this is a class, validate its value and its properties.
            else if (traverseProperties && entity.GetType().IsClass && entity.GetType() != typeof(string))
            {
                // Validate each property of the object
                var propertyMessages = entity.GetValidatableProperties()
                    .SelectMany(p => ValidateProperty(p, p.GetValue(entity), parentContext));
                messages = messages.Concat(propertyMessages);
            }

            // Validate the value of the object itself
            var valueMessages = ValidateObjectValue(entity, collectionRules, parentContext);
            return messages.Concat(valueMessages);
        }
 /// <summary>
 /// An x-ms-pageable extension passes this rule if the value for nextLinkName refers to a string property
 /// that exists on the schema for the 200 response of the parent operation.
 /// </summary>
 /// <param name="pageable"></param>
 /// <param name="context"></param>
 /// <param name="formatParameters"></param>
 /// <returns></returns>
 public override bool IsValid(object pageable, RuleContext context, out object[] formatParameters)
 {
     // Get the name of the property defined by nextLinkName in the spec
     var nextLinkPropertyName = (pageable as JContainer)?[ExtensionNextLinkPropertyName]?.ToString();
     if (!string.IsNullOrEmpty(nextLinkPropertyName))
     {
         var schema = Get200ResponseSchema(context);
         var serviceDefinition = context.GetServiceDefinition();
         // Try to find the property in this schema or its ancestors
         if (schema.FindPropertyInChain(serviceDefinition, nextLinkPropertyName) == null)
         {
             formatParameters = new string[] { nextLinkPropertyName };
             return false;
         }
     }
     formatParameters = new string[0];
     return true;
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Overridable method that lets a child rule specify if <paramref name="entity"/> passes validation
 /// </summary>
 /// <param name="entity"></param>
 /// <returns></returns>
 public virtual bool IsValid(object entity, RuleContext context) => IsValid(entity);
Ejemplo n.º 6
0
 public virtual bool IsValid(object entity, RuleContext context, out object[] formatParameters)
 {
     formatParameters = new object[0];
     return IsValid(entity, context);
 }
Ejemplo n.º 7
0
 /// <summary>
 /// Returns the validation messages resulting from validating this object
 /// </summary>
 /// <param name="entity">The object to validate</param>
 /// <returns></returns>
 public abstract IEnumerable<ValidationMessage> GetValidationMessages(object entity, RuleContext context);
 /// <summary>
 /// An x-ms-pageable extension passes this rule if the operation that this extension is defined on has a 200
 /// response defined
 /// </summary>
 /// <param name="pageable"></param>
 /// <param name="context"></param>
 /// <param name="formatParameters"></param>
 /// <returns></returns>
 public override bool IsValid(object pageable, RuleContext context) => Get200ResponseSchema(context) != null;
Ejemplo n.º 9
0
        private IEnumerable <ValidationMessage> ValidateProperty(PropertyInfo prop, object value, RuleContext parentContext)
        {
            // Uses the property name resolver to get the name to use in the path of messages
            var propName = resolver(prop);
            // Determine if anything about this property indicates that it shouldn't be traversed further
            var shouldTraverseObject = prop.IsTraversableProperty();
            // Create the context that's available to rules that validate this value
            var ruleContext = parentContext.CreateChild(value, propName);

            // Get any rules defined on this property and any defined as applying to the collection
            var propertyRules   = prop.GetValidationRules();
            var collectionRules = prop.GetValidationCollectionRules();

            // Validate the value of this property against any rules for it
            var propertyMessages = propertyRules.SelectMany(r => r.GetValidationMessages(value, ruleContext));

            // Recursively validate the property (e.g. its properties or any list/dictionary entries),
            // passing any rules that apply to this collection)
            var childrenMessages = RecursiveValidate(value, ruleContext, collectionRules, shouldTraverseObject);

            return(propertyMessages.Concat(childrenMessages)
                   .Select(e => e.AppendToPath(propName)));
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Validates an object value
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="collectionRules"></param>
        /// <param name="parentContext"></param>
        /// <returns></returns>
        private IEnumerable <ValidationMessage> ValidateObjectValue(object entity,
                                                                    IEnumerable <Rule> collectionRules, RuleContext parentContext)
        {
            // Get any rules defined for the class of the entity
            var classRules = entity.GetType().GetValidationRules();

            // Combine the class rules with any rules that apply to the collection that the entity is part of
            classRules = collectionRules.Concat(classRules);

            // Apply each rule for the entity
            return(classRules.SelectMany(rule => rule.GetValidationMessages(entity, parentContext)));
        }
Ejemplo n.º 11
0
        private IEnumerable<ValidationMessage> ValidateProperty(PropertyInfo prop, object value, RuleContext parentContext)
        {
            // Uses the property name resolver to get the name to use in the path of messages
            var propName = resolver(prop);
            // Determine if anything about this property indicates that it shouldn't be traversed further 
            var shouldTraverseObject = prop.IsTraversableProperty();
            // Create the context that's available to rules that validate this value
            var ruleContext = parentContext.CreateChild(value, propName);

            // Get any rules defined on this property and any defined as applying to the collection
            var propertyRules = prop.GetValidationRules();
            var collectionRules = prop.GetValidationCollectionRules();

            // Validate the value of this property against any rules for it
            var propertyMessages = propertyRules.SelectMany(r => r.GetValidationMessages(value, ruleContext));

            // Recursively validate the property (e.g. its properties or any list/dictionary entries),
            // passing any rules that apply to this collection)
            var childrenMessages = RecursiveValidate(value, ruleContext, collectionRules, shouldTraverseObject);

            return propertyMessages.Concat(childrenMessages)
                .Select(e => e.AppendToPath(propName));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Validates an object value 
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="collectionRules"></param>
        /// <param name="parentContext"></param>
        /// <returns></returns>
        private IEnumerable<ValidationMessage> ValidateObjectValue(object entity,
            IEnumerable<Rule> collectionRules, RuleContext parentContext)
        {
            // Get any rules defined for the class of the entity
            var classRules = entity.GetType().GetValidationRules();

            // Combine the class rules with any rules that apply to the collection that the entity is part of
            classRules = collectionRules.Concat(classRules);

            // Apply each rule for the entity
            return classRules.SelectMany(rule => rule.GetValidationMessages(entity, parentContext));
        }