Example #1
0
        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());
        }
Example #2
0
        // 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);
        }
Example #3
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
        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));
     }
 }