public MetadataOverrideScope(ModelMetadata metadata) { if (metadata == null) { throw new ArgumentNullException("metadata"); } if (metadata.ModelType == null) { throw new ArgumentException("Need ModelType", "metadata"); } _oldMetadataProvider = ModelMetadataProviders.Current; _metadata = metadata; _modelType = metadata.ModelType; // Mock a ModelMetadataProvider which delegates to the old one in most cases. No need to special-case // GetMetadataForProperties() because product code uses it only within ModelMetadata.Properties and our // metadata instance will call _oldMetadataProvider there. var metadataProvider = new Mock<ModelMetadataProvider>(); metadataProvider .Setup(p => p.GetMetadataForProperties(It.IsAny<object>(), It.IsAny<Type>())) .Returns((object container, Type containerType) => _oldMetadataProvider.GetMetadataForProperties(container, containerType)); metadataProvider .Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>())) .Returns((Func<object> modelAccessor, Type modelType) => _oldMetadataProvider.GetMetadataForType(modelAccessor, modelType)); // When metadata for _modelType is requested, then return a clone of the provided metadata instance. // GetMetadataForProperty() is important because the static discovery methods (e.g. // ModelMetadata.FromLambdaExpression) use it. metadataProvider .Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), _modelType)) .Returns((Func<object> modelAccessor, Type modelType) => GetMetadataForType(modelAccessor, modelType)); metadataProvider .Setup(p => p.GetMetadataForProperty(It.IsAny<Func<object>>(), It.IsAny<Type>(), It.IsAny<string>())) .Returns((Func<object> modelAccessor, Type containerType, string propertyName) => GetMetadataForProperty(modelAccessor, containerType, propertyName)); // Calls to GetMetadataForProperties for the modelType are incorrect because _metadata.Provider must // reference _oldMetadataProvider and not this mock. metadataProvider .Setup(p => p.GetMetadataForProperty(It.IsAny<Func<object>>(), _modelType, It.IsAny<string>())) .Throws<InvalidOperationException>(); // Finally make our ModelMetadataProvider visible everywhere. ModelMetadataProviders.Current = metadataProvider.Object; }
/// <summary> /// Determines whether the <paramref name="model"/> is valid and adds any validation errors to the <paramref name="actionContext"/>'s <see cref="ModelStateDictionary"/> /// </summary> /// <param name="model">The model to be validated.</param> /// <param name="type">The <see cref="Type"/> to use for validation.</param> /// <param name="metadataProvider">The <see cref="ModelMetadataProvider"/> used to provide the model metadata.</param> /// <param name="actionContext">The <see cref="HttpActionContext"/> within which the model is being validated.</param> /// <param name="keyPrefix">The <see cref="string"/> to append to the key for any validation errors.</param> /// <returns><c>true</c>if <paramref name="model"/> is valid, <c>false</c> otherwise.</returns> public bool Validate(object model, Type type, ModelMetadataProvider metadataProvider, HttpActionContext actionContext, string keyPrefix) { if (type == null) { throw Error.ArgumentNull("type"); } if (metadataProvider == null) { throw Error.ArgumentNull("metadataProvider"); } if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } if (model != null && !ShouldValidateType(model.GetType())) { return(true); } ModelValidatorProvider[] validatorProviders = actionContext.GetValidatorProviders().ToArray(); // Optimization : avoid validating the object graph if there are no validator providers if (validatorProviders == null || validatorProviders.Length == 0) { return(true); } ModelMetadata metadata = metadataProvider.GetMetadataForType(() => model, type); ValidationContext validationContext = new ValidationContext() { MetadataProvider = metadataProvider, ActionContext = actionContext, ValidatorCache = actionContext.GetValidatorCache(), ModelState = actionContext.ModelState, Visited = new HashSet <object>(ReferenceEqualityComparer.Instance), KeyBuilders = new Stack <IKeyBuilder>(), RootPrefix = keyPrefix }; return(ValidateNodeAndChildren(metadata, validationContext, container: null, validators: null)); }
public bool Validate(object model, Type type, ModelMetadataProvider metadataProvider, HttpActionContext actionContext, string keyPrefix) { if (type == null) { throw new ArgumentNullException("type"); } if (metadataProvider == null) { throw new ArgumentNullException("metadataProvider"); } if (actionContext == null) { throw new ArgumentNullException("actionContext"); } if (model != null && MediaTypeFormatterCollection.IsTypeExcludedFromValidation(model.GetType())) { // no validation for some DOM like types return(true); } ModelValidatorProvider[] validatorProviders = actionContext.GetValidatorProviders().ToArray(); // Optimization : avoid validating the object graph if there are no validator providers if (validatorProviders == null || validatorProviders.Length == 0) { return(true); } ModelMetadata metadata = metadataProvider.GetMetadataForType(() => model, type); ValidationContext validationContext = new ValidationContext { MetadataProvider = metadataProvider, ActionContext = actionContext, ModelState = actionContext.ModelState, Visited = new HashSet <object>(), KeyBuilders = new Stack <IKeyBuilder>(), RootPrefix = keyPrefix }; return(this.ValidateNodeAndChildren(metadata, validationContext, container: null)); }
private ModelBindingContext GetModelBindingContext(ModelMetadataProvider metadataProvider, HttpActionContext actionContext) { string name = Descriptor.ParameterName; Type type = Descriptor.ParameterType; string prefix = Descriptor.Prefix; IValueProvider vp = CompositeValueProviderFactory.GetValueProvider(actionContext, _valueProviderFactories); ModelBindingContext ctx = new ModelBindingContext() { ModelName = prefix ?? name, FallbackToEmptyPrefix = prefix == null, // only fall back if prefix not specified ModelMetadata = metadataProvider.GetMetadataForType(null, type), ModelState = actionContext.ModelState, ValueProvider = vp }; return(ctx); }
// Helper for ReadAs() to get a ModelBindingContext to invoke model binding over FormUrl data. private static ModelBindingContext CreateModelBindingContext(HttpActionContext actionContext, string modelName, Type type, IValueProvider vp) { Contract.Assert(actionContext != null); Contract.Assert(type != null); Contract.Assert(vp != null); ServicesContainer cs = actionContext.ControllerContext.Configuration.Services; ModelMetadataProvider metadataProvider = cs.GetModelMetadataProvider(); ModelBindingContext ctx = new ModelBindingContext() { ModelName = modelName, FallbackToEmptyPrefix = false, ModelMetadata = metadataProvider.GetMetadataForType(null, type), ModelState = actionContext.ModelState, ValueProvider = vp }; return(ctx); }
/// <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); } } } } }
public static bool TryBindStrongModel <TModel>( ControllerContext controllerContext, ExtensibleModelBindingContext parentBindingContext, string propertyName, ModelMetadataProvider metadataProvider, out TModel model ) { ExtensibleModelBindingContext propertyBindingContext = new ExtensibleModelBindingContext(parentBindingContext) { ModelMetadata = metadataProvider.GetMetadataForType(null, typeof(TModel)), ModelName = ModelBinderUtil.CreatePropertyModelName( parentBindingContext.ModelName, propertyName ) }; IExtensibleModelBinder binder = parentBindingContext.ModelBinderProviders.GetBinder( controllerContext, propertyBindingContext ); if (binder != null) { if (binder.BindModel(controllerContext, propertyBindingContext)) { object untypedModel = propertyBindingContext.Model; model = ModelBinderUtil.CastOrDefault <TModel>(untypedModel); parentBindingContext.ValidationNode.ChildNodes.Add( propertyBindingContext.ValidationNode ); return(true); } } model = default(TModel); return(false); }
public void Map(IDynamicDataModelSchema details, Type modelType) { Condition.Requires(details).IsNotNull(); Condition.Requires(modelType).IsNotNull(); var dataModelMetaData = _modelMetadataProvider.GetMetadataForType(null, modelType); details.DataTemplateName = StringHelper.FirstNonEmpty( dataModelMetaData.TemplateHint, dataModelMetaData.DataTypeName ); var properiesMetaData = _modelMetadataProvider.GetMetadataForProperties(null, modelType); var dataModelProperties = new List <DynamicDataModelSchemaProperty>(); foreach (var propertyMetaData in properiesMetaData.OrderBy(p => p.Order)) { var property = new DynamicDataModelSchemaProperty(); property.Name = propertyMetaData.PropertyName; property.DisplayName = propertyMetaData.DisplayName; property.Description = propertyMetaData.Description; property.IsRequired = propertyMetaData.IsRequired; property.DataTemplateName = StringHelper.FirstNonEmpty( propertyMetaData.TemplateHint, propertyMetaData.DataTypeName, propertyMetaData.IsNullableValueType ? propertyMetaData.ModelType.GenericTypeArguments[0].Name : propertyMetaData.ModelType.Name ); property.AdditionalAttributes = propertyMetaData.AdditionalValues; dataModelProperties.Add(property); } details.DataModelProperties = dataModelProperties.ToArray(); }
public static bool TryBindStrongModel <TModel>( this HttpActionContext actionContext, ModelBindingContext parentBindingContext, string propertyName, ModelMetadataProvider metadataProvider, out TModel model ) { if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } ModelBindingContext propertyBindingContext = new ModelBindingContext( parentBindingContext ) { ModelMetadata = metadataProvider.GetMetadataForType(null, typeof(TModel)), ModelName = ModelBindingHelper.CreatePropertyModelName( parentBindingContext.ModelName, propertyName ) }; if (actionContext.Bind(propertyBindingContext)) { object untypedModel = propertyBindingContext.Model; model = ModelBindingHelper.CastOrDefault <TModel>(untypedModel); parentBindingContext.ValidationNode.ChildNodes.Add( propertyBindingContext.ValidationNode ); return(true); } model = default(TModel); return(false); }
private void BuildColumns() { var modelMetadata = _metadataProvider.GetMetadataForType(() => null, typeof(T)); foreach (var property in modelMetadata.Properties) { if (!property.ShowForDisplay) { continue; } var column = For(PropertyToExpression(property)); if (!string.IsNullOrEmpty(property.DisplayName)) { column.Named(property.DisplayName); } if (!string.IsNullOrEmpty(property.DisplayFormatString)) { column.Format(property.DisplayFormatString); } } }
public AutoColumnGridModel(ModelMetadataProvider metadataProvider) { var modelMetadata = metadataProvider.GetMetadataForType(() => null, typeof(T)); foreach (var property in modelMetadata.Properties) { if (!property.ShowForDisplay) { continue; } var column = Column.For(PropertyToExpression(property)); if (!string.IsNullOrEmpty(property.DisplayName)) { column.Named(property.DisplayName); } if (!string.IsNullOrEmpty(property.DisplayFormatString)) { column.Format(property.DisplayFormatString); } } }
private object BindToModel(IDictionary <string, object> data, Type type, IFormatterLogger formatterLogger) { if (data == null) { throw new ArgumentNullException(nameof(data)); } if (type == null) { throw new ArgumentNullException(nameof(type)); } HttpConfiguration config = GlobalConfiguration.Configuration; // if there is a requiredMemberSelector set, use this one by replacing the validator provider bool validateRequiredMembers = RequiredMemberSelector != null && formatterLogger != null; if (validateRequiredMembers) { config.Services.Replace(typeof(ModelValidatorProvider), new RequiredMemberModelValidatorProvider(RequiredMemberSelector)); } // create a action context for model binding HttpActionContext actionContext = new HttpActionContext { ControllerContext = new HttpControllerContext { Configuration = config, ControllerDescriptor = new HttpControllerDescriptor { Configuration = config } } }; // create model binder context NameValuePairsValueProvider valueProvider = new NameValuePairsValueProvider(data, CultureInfo.InvariantCulture); ModelMetadataProvider metadataProvider = actionContext.ControllerContext.Configuration.Services.GetModelMetadataProvider(); ModelMetadata metadata = metadataProvider.GetMetadataForType(null, type); ModelBindingContext modelBindingContext = new ModelBindingContext { ModelName = string.Empty, FallbackToEmptyPrefix = false, ModelMetadata = metadata, ModelState = actionContext.ModelState, ValueProvider = valueProvider }; // bind model CompositeModelBinderProvider modelBinderProvider = new CompositeModelBinderProvider(config.Services.GetModelBinderProviders()); IModelBinder binder = modelBinderProvider.GetBinder(config, type); bool haveResult = binder.BindModel(actionContext, modelBindingContext); // log validation errors if (formatterLogger != null) { foreach (KeyValuePair <string, ModelState> modelStatePair in actionContext.ModelState) { foreach (ModelError modelError in modelStatePair.Value.Errors) { if (modelError.Exception != null) { formatterLogger.LogError(modelStatePair.Key, modelError.Exception); } else { formatterLogger.LogError(modelStatePair.Key, modelError.ErrorMessage); } } } } return(haveResult ? modelBindingContext.Model : GetDefaultValueForType(type)); }
void UpdateBindingInfo(ActionParameterContext context, ParameterDescriptor parameter) { var parameterType = parameter.ParameterType; var bindingInfo = parameter.BindingInfo; if (bindingInfo == null || bindingInfo.BindingSource == null) { var metadata = ModelMetadataProvider.GetMetadataForType(parameterType); if (bindingInfo == null) { parameter.BindingInfo = bindingInfo = new BindingInfo() { BindingSource = metadata.BindingSource }; } else { bindingInfo.BindingSource = metadata.BindingSource; } } if (bindingInfo.BindingSource == Custom) { if (parameterType.IsODataQueryOptions() || parameterType.IsODataPath()) { bindingInfo.BindingSource = Special; } } if (bindingInfo.BindingSource != null) { return; } var key = default(IEdmNamedElement); var paramName = parameter.Name; var source = Query; switch (context.RouteContext.ActionType) { case EntitySet: var keys = context.RouteContext.EntitySet.EntityType().Key().ToArray(); key = keys.FirstOrDefault(k => k.Name.Equals(paramName, OrdinalIgnoreCase)); if (key == null) { var template = context.Templates[0].PathTemplate; var segments = template.Segments.OfType <KeySegmentTemplate>(); if (segments.SelectMany(s => s.ParameterMappings.Values).Any(name => name.Equals(paramName, OrdinalIgnoreCase))) { source = Path; } } else { source = Path; } break; case BoundOperation: case UnboundOperation: var operation = context.RouteContext.Operation; if (operation == null) { break; } key = operation.Parameters.FirstOrDefault(p => p.Name.Equals(paramName, OrdinalIgnoreCase)); if (key == null) { if (operation.IsBound) { goto case EntitySet; } } else { source = Path; } break; } bindingInfo.BindingSource = source; }
/// <summary> /// Deserialize the form data to the given type, using model binding. /// </summary> /// <param name="formData">collection with parsed form url data</param> /// <param name="type">target type to read as</param> /// <param name="modelName">null or empty to read the entire form as a single object. This is common for body data. /// <param name="requiredMemberSelector">The <see cref="IRequiredMemberSelector"/> used to determine required members.</param> /// <param name="formatterLogger">The <see cref="IFormatterLogger"/> to log events to.</param> /// Or the name of a model to do a partial binding against the form data. This is common for extracting individual fields.</param> /// <returns>best attempt to bind the object. The best attempt may be null.</returns> public static object ReadAs(this FormDataCollection formData, Type type, string modelName, IRequiredMemberSelector requiredMemberSelector, IFormatterLogger formatterLogger) { if (formData == null) { throw Error.ArgumentNull("formData"); } if (type == null) { throw Error.ArgumentNull("type"); } if (modelName == null) { modelName = string.Empty; } using (HttpConfiguration config = new HttpConfiguration()) { bool validateRequiredMembers = requiredMemberSelector != null && formatterLogger != null; if (validateRequiredMembers) { // Set a ModelValidatorProvider that understands the IRequiredMemberSelector config.Services.Replace(typeof(ModelValidatorProvider), new RequiredMemberModelValidatorProvider(requiredMemberSelector)); } // Looks like HttpActionContext is just a way of getting to the config, which we really // just need to get a list of modelbinderPRoviders for composition. HttpControllerContext controllerContext = new HttpControllerContext() { Configuration = config }; HttpActionContext actionContext = new HttpActionContext { ControllerContext = controllerContext }; ModelMetadataProvider metadataProvider = config.Services.GetModelMetadataProvider(); // Create default over config IEnumerable <ModelBinderProvider> providers = config.Services.GetModelBinderProviders(); ModelBinderProvider modelBinderProvider = new CompositeModelBinderProvider(providers); IValueProvider vp = formData.GetJQueryValueProvider(); ModelBindingContext ctx = new ModelBindingContext() { ModelName = modelName, FallbackToEmptyPrefix = false, ModelMetadata = metadataProvider.GetMetadataForType(null, type), ModelState = actionContext.ModelState, ValueProvider = vp }; IModelBinder binder = modelBinderProvider.GetBinder(actionContext, ctx); bool haveResult = binder.BindModel(actionContext, ctx); // Log model binding errors if (validateRequiredMembers) { Contract.Assert(formatterLogger != null); foreach (KeyValuePair <string, ModelState> modelStatePair in actionContext.ModelState) { foreach (ModelError modelError in modelStatePair.Value.Errors) { formatterLogger.LogError(modelStatePair.Key, modelError.ErrorMessage); } } } if (haveResult) { return(ctx.Model); } return(null); } }
public MetadataOverrideScope(ModelMetadata metadata) { if (metadata == null) { throw new ArgumentNullException("metadata"); } if (metadata.ModelType == null) { throw new ArgumentException("Need ModelType", "metadata"); } _oldMetadataProvider = ModelMetadataProviders.Current; _metadata = metadata; _modelType = metadata.ModelType; // Mock a ModelMetadataProvider which delegates to the old one in most cases. No need to special-case // GetMetadataForProperties() because product code uses it only within ModelMetadata.Properties and our // metadata instance will call _oldMetadataProvider there. var metadataProvider = new Mock <ModelMetadataProvider>(); metadataProvider .Setup(p => p.GetMetadataForProperties(It.IsAny <object>(), It.IsAny <Type>())) .Returns( (object container, Type containerType) => _oldMetadataProvider.GetMetadataForProperties(container, containerType) ); metadataProvider .Setup(p => p.GetMetadataForType(It.IsAny <Func <object> >(), It.IsAny <Type>())) .Returns( (Func <object> modelAccessor, Type modelType) => _oldMetadataProvider.GetMetadataForType(modelAccessor, modelType) ); // When metadata for _modelType is requested, then return a clone of the provided metadata instance. // GetMetadataForProperty() is important because the static discovery methods (e.g. // ModelMetadata.FromLambdaExpression) use it. metadataProvider .Setup(p => p.GetMetadataForType(It.IsAny <Func <object> >(), _modelType)) .Returns( (Func <object> modelAccessor, Type modelType) => GetMetadataForType(modelAccessor, modelType) ); metadataProvider .Setup( p => p.GetMetadataForProperty( It.IsAny <Func <object> >(), It.IsAny <Type>(), It.IsAny <string>() ) ) .Returns( (Func <object> modelAccessor, Type containerType, string propertyName) => GetMetadataForProperty(modelAccessor, containerType, propertyName) ); // Calls to GetMetadataForProperties for the modelType are incorrect because _metadata.Provider must // reference _oldMetadataProvider and not this mock. metadataProvider .Setup( p => p.GetMetadataForProperty( It.IsAny <Func <object> >(), _modelType, It.IsAny <string>() ) ) .Throws <InvalidOperationException>(); // Finally make our ModelMetadataProvider visible everywhere. ModelMetadataProviders.Current = metadataProvider.Object; }
public override ModelMetadata GetMetadataForType(Func <object> modelAccessor, Type modelType) { return(_innerProvider.GetMetadataForType(modelAccessor, modelType)); }
public static ModelMetadata CollectionModelMetadata <T>(this ViewDataDictionary viewData, ModelMetadataProvider provider) { return(provider.GetMetadataForType(typeof(T))); }
public static ModelMetadata CollectionModelMetadata(this ViewDataDictionary viewData, ModelMetadataProvider provider) { var type = viewData.ModelMetadata.ModelType.GenericTypeArguments.FirstOrDefault(); return(provider.GetMetadataForType(type)); }