public void BindModel_UnsuccessfulBind_SimpleTypeNoFallback_ReturnsNull() { // Arrange HttpActionContext actionContext = ContextUtil.CreateActionContext(GetHttpControllerContext()); Mock <ModelBinderProvider> mockBinderProvider = new Mock <ModelBinderProvider>(); mockBinderProvider.Setup(o => o.GetBinder(It.IsAny <HttpConfiguration>(), It.IsAny <Type>())).Returns((IModelBinder)null).Verifiable(); List <ModelBinderProvider> binderProviders = new List <ModelBinderProvider>() { mockBinderProvider.Object }; CompositeModelBinderProvider shimBinderProvider = new CompositeModelBinderProvider(binderProviders); CompositeModelBinder shimBinder = new CompositeModelBinder(shimBinderProvider.GetBinder(null, null)); ModelBindingContext bindingContext = new ModelBindingContext { FallbackToEmptyPrefix = true, ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)), //ModelState = executionContext.Controller.ViewData.ModelState }; // Act bool isBound = shimBinder.BindModel(actionContext, bindingContext); // Assert Assert.False(isBound); Assert.Null(bindingContext.Model); Assert.True(bindingContext.ModelState.IsValid); mockBinderProvider.Verify(); mockBinderProvider.Verify(o => o.GetBinder(It.IsAny <HttpConfiguration>(), It.IsAny <Type>()), Times.AtMostOnce()); }
// Helper for ReadAs() to get a ModelBinderProvider to read FormUrl data. private static ModelBinderProvider CreateModelBindingProvider(HttpActionContext actionContext) { Contract.Assert(actionContext != null); ServicesContainer cs = actionContext.ControllerContext.Configuration.Services; IEnumerable <ModelBinderProvider> providers = cs.GetModelBinderProviders(); ModelBinderProvider modelBinderProvider = new CompositeModelBinderProvider(providers); return(modelBinderProvider); }
public static string ModelBinderToString(ModelBinderProvider provider) { Contract.Assert(provider != null); CompositeModelBinderProvider composite = provider as CompositeModelBinderProvider; if (composite == null) { return(provider.GetType().Name); } string modelBinderList = string.Join(", ", composite.Providers.Select <ModelBinderProvider, string>(ModelBinderToString)); return(provider.GetType().Name + "(" + modelBinderList + ")"); }
public void ModelBinderToString_With_CompositeModelBinder_Formats() { // Arrange ModelBinderProvider innerProvider1 = new SimpleModelBinderProvider(typeof(int), () => null); ModelBinderProvider innerProvider2 = new ArrayModelBinderProvider(); CompositeModelBinderProvider compositeProvider = new CompositeModelBinderProvider(new ModelBinderProvider[] { innerProvider1, innerProvider2 }); string expected = String.Format( "{0}({1}, {2})", typeof(CompositeModelBinderProvider).Name, typeof(SimpleModelBinderProvider).Name, typeof(ArrayModelBinderProvider).Name); // Act string actual = FormattingUtilities.ModelBinderToString(compositeProvider); // Assert Assert.Equal(expected, actual); }
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { bindingContext.ModelMetadata.AdditionalValues.Add(key, this); //this is the default webapi model binder provider var provider = new CompositeModelBinderProvider(actionContext.ControllerContext.Configuration.Services.GetModelBinderProviders()); //the default webapi model binder var binder = provider.GetBinder(actionContext.ControllerContext.Configuration, bindingContext.ModelType); var a = new DefaultActionValueBinder().GetBinding(actionContext.ActionDescriptor); a.ExecuteBindingAsync(actionContext, new System.Threading.CancellationToken()).Wait(); //let the default binder do it's thing var result = binder.BindModel(actionContext, bindingContext); bindingContext.ModelMetadata.AdditionalValues.Remove(key); return(result); }
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)); } using (var config = new HttpConfiguration()) { // if there is a requiredMemberSelector set, use this one by replacing the validator provider var validateRequiredMembers = RequiredMemberSelector != null && formatterLogger != null; if (validateRequiredMembers) { config.Services.Replace(typeof(ModelValidatorProvider), new RequiredMemberModelValidatorProvider(RequiredMemberSelector)); } // create a action context for model binding var actionContext = new HttpActionContext { ControllerContext = new HttpControllerContext { Configuration = config, ControllerDescriptor = new HttpControllerDescriptor { Configuration = config } } }; // create model binder context var valueProvider = new NameValuePairsValueProvider(data, CultureInfo.InvariantCulture); var metadataProvider = actionContext.ControllerContext.Configuration.Services.GetModelMetadataProvider(); var metadata = metadataProvider.GetMetadataForType(null, type); var modelBindingContext = new ModelBindingContext { ModelName = string.Empty, FallbackToEmptyPrefix = false, ModelMetadata = metadata, ModelState = actionContext.ModelState, ValueProvider = valueProvider }; // bind model var modelBinderProvider = new CompositeModelBinderProvider(config.Services.GetModelBinderProviders()); var binder = modelBinderProvider.GetBinder(config, type); var haveResult = binder.BindModel(actionContext, modelBindingContext); // log validation errors if (formatterLogger != null) { foreach (var modelStatePair in actionContext.ModelState) { foreach (var 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)); } }
/// <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); } }
// apply dictionary to model instance 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)); } using (var config = new HttpConfiguration()) { if (RequiredMemberSelector != null && formatterLogger != null) { config.Services.Replace( typeof(ModelValidatorProvider), new RequiredMemberModelValidatorProvider(RequiredMemberSelector)); } var actionContext = new HttpActionContext { ControllerContext = new HttpControllerContext { Configuration = config, ControllerDescriptor = new HttpControllerDescriptor { Configuration = config } } }; // workaround possible locale mismatch var cultureBugWorkaround = CultureInfo.CurrentCulture.Clone() as CultureInfo; cultureBugWorkaround.NumberFormat = CultureInfo.InvariantCulture.NumberFormat; var valueProvider = new NameValuePairsValueProvider(data, cultureBugWorkaround); var metadataProvider = actionContext.ControllerContext.Configuration.Services.GetModelMetadataProvider(); var metadata = metadataProvider.GetMetadataForType(null, type); var modelBindingContext = new ModelBindingContext { ModelName = string.Empty, FallbackToEmptyPrefix = false, ModelMetadata = metadata, ModelState = actionContext.ModelState, ValueProvider = valueProvider }; // bind our model var modelBinderProvider = new CompositeModelBinderProvider(config.Services.GetModelBinderProviders()); var binder = modelBinderProvider.GetBinder(config, type); var haveResult = binder.BindModel(actionContext, modelBindingContext); // store validation errors if (formatterLogger != null) { foreach (var modelStatePair in actionContext.ModelState) { foreach (var 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)); } }