public override IEnumerable<ModelValidationResult> Validate(ModelMetadata metadata, object container) { bool propertiesValid = true; foreach (ModelMetadata propertyMetadata in metadata.Properties) { foreach (ModelValidator propertyValidator in propertyMetadata.GetValidators(ValidatorProviders)) { foreach (ModelValidationResult propertyResult in propertyValidator.Validate(metadata, container)) { propertiesValid = false; yield return new ModelValidationResult { MemberName = ModelBindingHelper.CreatePropertyModelName(propertyMetadata.PropertyName, propertyResult.MemberName), Message = propertyResult.Message }; } } } if (propertiesValid) { foreach (ModelValidator typeValidator in metadata.GetValidators(ValidatorProviders)) { foreach (ModelValidationResult typeResult in typeValidator.Validate(metadata, container)) { yield return typeResult; } } } }
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; if (!TryGetValue(cacheKey, out validators)) { _cacheLock.EnterWriteLock(); try { // Check the cache again in case the value was computed and added to the cache while we were waiting on the write lock if (!_validatorCache.TryGetValue(cacheKey, out validators)) { // Compute validators validators = metadata.GetValidators(_validatorProviders.Value).ToArray(); _validatorCache.Add(cacheKey, validators); } } finally { _cacheLock.ExitWriteLock(); } } return validators; }
public ModelValidator[] GetValidators(ModelMetadata metadata) { ModelValidator[] validators; if (!_validatorCache.TryGetValue(metadata.CacheKey, out validators)) { // Compute validators // There are no side-effects if the same validators are created more than once validators = metadata.GetValidators(_validatorProviders.Value).ToArray(); _validatorCache.TryAdd(metadata.CacheKey, validators); } return validators; }
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; if (!_validatorCache.TryGetValue(cacheKey, out validators)) { // Compute validators // There are no side-effects if the same validators are created more than once validators = metadata.GetValidators(_validatorProviders.Value).ToArray(); _validatorCache.TryAdd(cacheKey, validators); } 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, string key) { bool isValid = true; foreach (ModelValidator validator in metadata.GetValidators(validationContext.ValidatorProviders)) { foreach (ModelValidationResult error in validator.Validate(container)) { validationContext.ModelState.AddModelError(key, error.Message); isValid = false; } } return isValid; }
private IEnumerable<ModelValidator> GetValidators(IEnumerable<ModelValidatorProvider> validatorProviders, 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); // This retrieval is implemented as a TryGetValue/TryAdd instead of a GetOrAdd to avoid the performance cost of creating delegates IEnumerable<ModelValidator> validators; if (!_validatorCache.TryGetValue(cacheKey, out validators)) { validators = metadata.GetValidators(validatorProviders).ToArray(); _validatorCache.TryAdd(cacheKey, validators); } return validators; }