Exemple #1
0
        public IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata)
        {
            // If metadata is for a property then containerType != null && propertyName != null
            // If metadata is for a type then containerType == null && propertyName == null, so we have to use modelType for the cache key.
            Type typeForCache = metadata.ContainerType ?? metadata.ModelType;
            Tuple<Type, string> cacheKey = Tuple.Create(typeForCache, metadata.PropertyName);
            ModelValidator[] validators;

            // Try to find validator into fast cache first
            if (!this.fastCache.TryGetValue(cacheKey, out validators))
            {
                if (!this.validatorCache.TryGetValue(cacheKey, out validators))
                {
                    // Compute validators
                    // There are no side-effects if the same validators are created more than once
                    validators = metadata.GetValidators(this.validatorProviders.Value).ToArray();
                    this.validatorCache.TryAdd(cacheKey, validators);
                }

                // Fastcache is out of sync. Resync it.
                // Resync could miss some addition to the validatorCache but it will be OK after a few iterations.
                // Works well if there is a lot of read operations 
                Interlocked.Exchange(ref this.fastCache, new Dictionary<Tuple<Type, string>, ModelValidator[]>(this.validatorCache));
            }

            return validators;
        }
        // Validates a single node (not including children)
        // Returns true if validation passes successfully
        private static bool ShallowValidate(ModelMetadata metadata, ValidationContext validationContext, object container)
        {
            Contract.Requires(validationContext != null);

            bool isValid = true;
            string key = null;
            IModelValidatorCache validatorCache = validationContext.ValidatorCache;
            ModelValidator[] validators;
            if (validatorCache == null)
            {
                // slow path: there is no validator cache on the configuration
                validators = metadata.GetValidators(validationContext.ValidatorProviders).AsArray();
            }
            else
            {
                validators = validatorCache.GetValidators(metadata).AsArray();
            }

            for (int index = 0; index < validators.Length; index++)
            {
                ModelValidator validator = validators[index];
                foreach (ModelValidationResult error in validator.Validate(metadata, container))
                {
                    if (key == null)
                    {
                        key = validationContext.RootPrefix;
                        foreach (IKeyBuilder keyBuilder in validationContext.KeyBuilders.Reverse())
                        {
                            key = keyBuilder.AppendTo(key);
                        }
                    }

                    validationContext.ModelState.AddModelError(key, error.Message);
                    isValid = false;
                }
            }

            return isValid;
        }