/// <summary> /// Validates a single node (not including children) /// </summary> /// <param name="metadata">Model Metadata</param> /// <param name="validationContext">Validation Context</param> /// <param name="container">The container.</param> /// <returns>True if validation passes successfully</returns> private static bool ShallowValidate(ModelMetadata metadata, InternalValidationContext validationContext, object container) { bool isValid = true; // Use the DependencyResolver to find any validators appropriate for this type IEnumerable <IValidator> validators = validationContext.Provider.GetValidators(metadata.ModelType, validationContext.Scope); foreach (IValidator validator in validators) { IValidatorSelector selector = new DefaultValidatorSelector(); var context = new ValidationContext(metadata.Model, new PropertyChain(), selector); ValidationResult result = validator.Validate(context); foreach (ValidationFailure error in result.Errors) { if (!validationContext.ModelState.ContainsKey(error.PropertyName)) { validationContext.ModelState.Add(error.PropertyName, new ModelState { Value = new ValueProviderResult(error.AttemptedValue, error.AttemptedValue.ToString(), CultureInfo.CurrentCulture) }); } validationContext.ModelState.AddModelError(error.PropertyName, error.ErrorMessage); isValid = false; } } return(isValid); }
private bool ValidateNodeAndChildren(ModelMetadata metadata, InternalValidationContext validationContext, object container) { bool isValid = true; object model = metadata.Model; // Optimization: we don't need to recursively traverse the graph for null and primitive types if (model != null && model.GetType().IsSimpleType()) { return ShallowValidate(metadata, validationContext, container); } // Check to avoid infinite recursion. This can happen with cycles in an object graph. if (validationContext.Visited.Contains(model)) { return true; } validationContext.Visited.Add(model); // Validate the children first - depth-first traversal var enumerableModel = model as IEnumerable; if (enumerableModel == null) { isValid = ValidateProperties(metadata, validationContext); } else { isValid = ValidateElements(enumerableModel, validationContext); } if (isValid && metadata.Model != null) { // Don't bother to validate this node if children failed. isValid = ShallowValidate(metadata, validationContext, container); } // Pop the object so that it can be validated again in a different path validationContext.Visited.Remove(model); return isValid; }
private bool ValidateProperties(ModelMetadata metadata, InternalValidationContext validationContext) { bool isValid = true; var propertyScope = new PropertyScope(); validationContext.KeyBuilders.Push(propertyScope); foreach (ModelMetadata childMetadata in validationContext.MetadataProvider.GetMetadataForProperties( metadata.Model, GetRealModelType(metadata))) { propertyScope.PropertyName = childMetadata.PropertyName; if (!ValidateNodeAndChildren(childMetadata, validationContext, metadata.Model)) { isValid = false; } } validationContext.KeyBuilders.Pop(); return isValid; }
private bool ValidateElements(IEnumerable model, InternalValidationContext validationContext) { bool isValid = true; Type elementType = GetElementType(model.GetType()); ModelMetadata elementMetadata = validationContext.MetadataProvider.GetMetadataForType(null, elementType); var elementScope = new ElementScope { Index = 0 }; validationContext.KeyBuilders.Push(elementScope); foreach (object element in model) { elementMetadata.Model = element; if (!ValidateNodeAndChildren(elementMetadata, validationContext, model)) { isValid = false; } elementScope.Index++; } validationContext.KeyBuilders.Pop(); return isValid; }
/// <summary> /// Pick out validation errors and turn these into a suitable exception structure /// </summary> /// <param name="actionContext">Action Context</param> public override void OnActionExecuting(HttpActionContext actionContext) { ModelStateDictionary modelState = actionContext.ModelState; if (modelState.IsValid) { // Only perform the FluentValidation if we've not already failed validation earlier on IDependencyScope scope = actionContext.Request.GetDependencyScope(); var mvp = scope.GetService(typeof(IFluentValidatorProvider)) as IFluentValidatorProvider; if (mvp != null) { ModelMetadataProvider metadataProvider = actionContext.GetMetadataProvider(); foreach (KeyValuePair <string, object> argument in actionContext.ActionArguments) { if (argument.Value != null && !argument.Value.GetType().IsSimpleType()) { ModelMetadata metadata = metadataProvider.GetMetadataForType( () => argument.Value, argument.Value.GetType() ); var validationContext = new InternalValidationContext { MetadataProvider = metadataProvider, ActionContext = actionContext, ModelState = actionContext.ModelState, Visited = new HashSet <object>(), KeyBuilders = new Stack <IKeyBuilder>(), RootPrefix = String.Empty, Provider = mvp, Scope = scope }; ValidateNodeAndChildren(metadata, validationContext, null); } } } } }
/// <summary> /// Pick out validation errors and turn these into a suitable exception structure /// </summary> /// <param name="actionContext">Action Context</param> public override void OnActionExecuting(HttpActionContext actionContext) { ModelStateDictionary modelState = actionContext.ModelState; if (modelState.IsValid) { // Only perform the FluentValidation if we've not already failed validation earlier on IDependencyScope scope = actionContext.Request.GetDependencyScope(); var mvp = scope.GetService(typeof(IFluentValidatorProvider)) as IFluentValidatorProvider; if (mvp != null) { ModelMetadataProvider metadataProvider = actionContext.GetMetadataProvider(); foreach (KeyValuePair<string, object> argument in actionContext.ActionArguments) { if (argument.Value != null && !argument.Value.GetType().IsSimpleType()) { ModelMetadata metadata = metadataProvider.GetMetadataForType( () => argument.Value, argument.Value.GetType() ); var validationContext = new InternalValidationContext { MetadataProvider = metadataProvider, ActionContext = actionContext, ModelState = actionContext.ModelState, Visited = new HashSet<object>(), KeyBuilders = new Stack<IKeyBuilder>(), RootPrefix = String.Empty, Provider = mvp, Scope = scope }; ValidateNodeAndChildren(metadata, validationContext, null); } } } } }
/// <summary> /// Validates a single node (not including children) /// </summary> /// <param name="metadata">Model Metadata</param> /// <param name="validationContext">Validation Context</param> /// <param name="container">The container.</param> /// <returns>True if validation passes successfully</returns> private static bool ShallowValidate(ModelMetadata metadata, InternalValidationContext validationContext, object container) { bool isValid = true; string key = null; // Use the DependencyResolver to find any validators appropriate for this type IEnumerable <IValidator> validators = validationContext.Provider.GetValidators(metadata.ModelType, validationContext.Scope); foreach (IValidator validator in validators) { IValidatorSelector selector = new DefaultValidatorSelector(); ValidationContext context = new ValidationContext(metadata.Model, new PropertyChain(), selector); ValidationResult result = validator.Validate(context); foreach (var error in result.Errors) { if (key == null) { key = validationContext.RootPrefix; foreach (IKeyBuilder keyBuilder in validationContext.KeyBuilders.Reverse()) { key = keyBuilder.AppendTo(key); } // Avoid adding model errors if the model state already contains model errors for that key // We can't perform this check earlier because we compute the key string only when we detect an error if (!validationContext.ModelState.IsValidField(key)) { return(false); } } validationContext.ModelState.AddModelError(key, JsonConvert.SerializeObject(error)); isValid = false; } } return(isValid); }
private bool ValidateProperties(ModelMetadata metadata, InternalValidationContext validationContext) { bool isValid = true; PropertyScope propertyScope = new PropertyScope(); validationContext.KeyBuilders.Push(propertyScope); foreach (ModelMetadata childMetadata in validationContext.MetadataProvider.GetMetadataForProperties( metadata.Model, GetRealModelType(metadata))) { propertyScope.PropertyName = childMetadata.PropertyName; if (!ValidateNodeAndChildren(childMetadata, validationContext, metadata.Model)) { isValid = false; } } validationContext.KeyBuilders.Pop(); return isValid; }
private bool ValidateNodeAndChildren(ModelMetadata metadata, InternalValidationContext validationContext, object container) { object model = metadata.Model; bool isValid = true; // Optimization: we don't need to recursively traverse the graph for null and primitive types if (model == null || model.GetType().IsSimpleType()) { return ShallowValidate(metadata, validationContext, container); } // Check to avoid infinite recursion. This can happen with cycles in an object graph. if (validationContext.Visited.Contains(model)) { return true; } validationContext.Visited.Add(model); // Validate the children first - depth-first traversal IEnumerable enumerableModel = model as IEnumerable; if (enumerableModel == null) { isValid = ValidateProperties(metadata, validationContext); } else { isValid = ValidateElements(enumerableModel, validationContext); } if (isValid) { // Don't bother to validate this node if children failed. isValid = ShallowValidate(metadata, validationContext, container); } // Pop the object so that it can be validated again in a different path validationContext.Visited.Remove(model); return isValid; }
private bool ValidateElements(IEnumerable model, InternalValidationContext validationContext) { bool isValid = true; Type elementType = GetElementType(model.GetType()); ModelMetadata elementMetadata = validationContext.MetadataProvider.GetMetadataForType(null, elementType); ElementScope elementScope = new ElementScope() { Index = 0 }; validationContext.KeyBuilders.Push(elementScope); foreach (object element in model) { elementMetadata.Model = element; if (!ValidateNodeAndChildren(elementMetadata, validationContext, model)) { isValid = false; } elementScope.Index++; } validationContext.KeyBuilders.Pop(); return isValid; }
/// <summary> /// Validates a single node (not including children) /// </summary> /// <param name="metadata">Model Metadata</param> /// <param name="validationContext">Validation Context</param> /// <param name="container">The container.</param> /// <returns>True if validation passes successfully</returns> private static bool ShallowValidate(ModelMetadata metadata, InternalValidationContext validationContext, object container) { bool isValid = true; string key = null; // Use the DependencyResolver to find any validators appropriate for this type IEnumerable<IValidator> validators = validationContext.Provider.GetValidators(metadata.ModelType, validationContext.Scope); foreach (IValidator validator in validators) { IValidatorSelector selector = new DefaultValidatorSelector(); ValidationContext context = new ValidationContext(metadata.Model, new PropertyChain(), selector); ValidationResult result = validator.Validate(context); foreach (var error in result.Errors) { if (key == null) { key = validationContext.RootPrefix; foreach (IKeyBuilder keyBuilder in validationContext.KeyBuilders.Reverse()) { key = keyBuilder.AppendTo(key); } // Avoid adding model errors if the model state already contains model errors for that key // We can't perform this check earlier because we compute the key string only when we detect an error if (!validationContext.ModelState.IsValidField(key)) { return false; } } validationContext.ModelState.AddModelError(key, JsonConvert.SerializeObject(error)); isValid = false; } } return isValid; }
/// <summary> /// Validates a single node (not including children) /// </summary> /// <param name="metadata">Model Metadata</param> /// <param name="validationContext">Validation Context</param> /// <param name="container">The container.</param> /// <returns>True if validation passes successfully</returns> private static bool ShallowValidate(ModelMetadata metadata, InternalValidationContext validationContext, object container) { bool isValid = true; // Use the DependencyResolver to find any validators appropriate for this type IEnumerable<IValidator> validators = validationContext.Provider.GetValidators(metadata.ModelType, validationContext.Scope); foreach (IValidator validator in validators) { IValidatorSelector selector = new DefaultValidatorSelector(); var context = new ValidationContext(metadata.Model, new PropertyChain(), selector); ValidationResult result = validator.Validate(context); foreach (ValidationFailure error in result.Errors) { if (!validationContext.ModelState.ContainsKey(error.PropertyName)) { validationContext.ModelState.Add(error.PropertyName, new ModelState { Value = new ValueProviderResult(error.AttemptedValue, error.AttemptedValue.ToString(), CultureInfo.CurrentCulture) }); } validationContext.ModelState.AddModelError(error.PropertyName, error.ErrorMessage); isValid = false; } } return isValid; }