/// <summary> /// Gets the collection of registered <see cref="ModelValidator"/> instances. /// </summary> /// <param name="actionContext">The context.</param> /// <param name="metadata">The metadata.</param> /// <returns>A collection of registered <see cref="ModelValidator"/> instances.</returns> public static IEnumerable <ModelValidator> GetValidators(this HttpActionContext actionContext, ModelMetadata metadata) { if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } IModelValidatorCache validatorCache = actionContext.GetValidatorCache(); return(actionContext.GetValidators(metadata, validatorCache)); }
internal static void GetRequiredPropertiesCollection(HttpActionContext actionContext, ModelBindingContext bindingContext, out HashSet<string> requiredProperties, out Dictionary<string, ModelValidator> requiredValidators, out HashSet<string> skipProperties) { requiredProperties = new HashSet<string>(StringComparer.OrdinalIgnoreCase); requiredValidators = new Dictionary<string, ModelValidator>(StringComparer.OrdinalIgnoreCase); skipProperties = new HashSet<string>(StringComparer.OrdinalIgnoreCase); // Use attributes on the property before attributes on the type. ICustomTypeDescriptor modelDescriptor = TypeDescriptorHelper.Get(bindingContext.ModelType); PropertyDescriptorCollection propertyDescriptors = modelDescriptor.GetProperties(); HttpBindingBehaviorAttribute typeAttr = modelDescriptor.GetAttributes().OfType<HttpBindingBehaviorAttribute>().SingleOrDefault(); foreach (PropertyDescriptor propertyDescriptor in propertyDescriptors) { string propertyName = propertyDescriptor.Name; ModelMetadata propertyMetadata = bindingContext.PropertyMetadata[propertyName]; ModelValidator requiredValidator = actionContext.GetValidators(propertyMetadata).Where(v => v.IsRequired).FirstOrDefault(); requiredValidators[propertyName] = requiredValidator; HttpBindingBehaviorAttribute propAttr = propertyDescriptor.Attributes.OfType<HttpBindingBehaviorAttribute>().SingleOrDefault(); HttpBindingBehaviorAttribute workingAttr = propAttr ?? typeAttr; if (workingAttr != null) { switch (workingAttr.Behavior) { case HttpBindingBehavior.Required: requiredProperties.Add(propertyName); break; case HttpBindingBehavior.Never: skipProperties.Add(propertyName); break; } } else if (requiredValidator != null) { requiredProperties.Add(propertyName); } } }
private void ValidateThis(HttpActionContext actionContext, ModelValidationNode parentNode) { ModelStateDictionary modelState = actionContext.ModelState; if (!modelState.IsValidField(ModelStateKey)) { return; // short-circuit } // If 'this' is null and there is no parent, we cannot validate, and // the DataAnnotationsModelValidator will throw. So we intercept here // to provide a catch-all value-required validation error if (parentNode == null && ModelMetadata.Model == null) { string trueModelStateKey = ModelBindingHelper.CreatePropertyModelName(ModelStateKey, ModelMetadata.GetDisplayName()); modelState.AddModelError(trueModelStateKey, SRResources.Validation_ValueNotFound); return; } _validators = actionContext.GetValidators(ModelMetadata); object container = TryConvertContainerToMetadataType(parentNode); foreach (ModelValidator validator in _validators) { foreach (ModelValidationResult validationResult in validator.Validate(ModelMetadata, container)) { string trueModelStateKey = ModelBindingHelper.CreatePropertyModelName(ModelStateKey, validationResult.MemberName); modelState.AddModelError(trueModelStateKey, validationResult.Message); } } }
private void ValidateProperties(HttpActionContext actionContext) { // Based off CompositeModelValidator. ModelStateDictionary modelState = actionContext.ModelState; // DevDiv Bugs #227802 - Caching problem in ModelMetadata requires us to manually regenerate // the ModelMetadata. object model = ModelMetadata.Model; ModelMetadata updatedMetadata = actionContext.GetMetadataProvider().GetMetadataForType(() => model, ModelMetadata.ModelType); foreach (ModelMetadata propertyMetadata in updatedMetadata.Properties) { // Only want to add errors to ModelState if something doesn't already exist for the property node, // else we could end up with duplicate or irrelevant error messages. string propertyKeyRoot = ModelBindingHelper.CreatePropertyModelName(ModelStateKey, propertyMetadata.PropertyName); if (modelState.IsValidField(propertyKeyRoot)) { foreach (ModelValidator propertyValidator in actionContext.GetValidators(propertyMetadata)) { foreach (ModelValidationResult propertyResult in propertyValidator.Validate(propertyMetadata, model)) { string thisErrorKey = ModelBindingHelper.CreatePropertyModelName(propertyKeyRoot, propertyResult.MemberName); modelState.AddModelError(thisErrorKey, propertyResult.Message); } } } } }