Пример #1
0
        public void CreateBinder_DoesNotCache_WhenTokenIsNull()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = Options.Create(new MvcOptions());

            options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(c =>
            {
                Assert.Equal(typeof(Employee), c.Metadata.ModelType);
                return(Mock.Of <IModelBinder>());
            }));

            var factory = new ModelBinderFactory(
                metadataProvider,
                options,
                GetServices());

            var context = new ModelBinderFactoryContext()
            {
                Metadata = metadataProvider.GetMetadataForType(typeof(Employee)),
            };

            // Act
            var result1 = factory.CreateBinder(context);
            var result2 = factory.CreateBinder(context);

            // Assert
            Assert.NotSame(result1, result2);
        }
Пример #2
0
        public void CreateBinder_NestedProperties()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = Options.Create(new MvcOptions());

            options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(c =>
            {
                if (c.Metadata.ModelType == typeof(Widget))
                {
                    Assert.NotNull(c.CreateBinder(c.Metadata.Properties[nameof(Widget.Id)]));
                    return(Mock.Of <IModelBinder>());
                }
                else if (c.Metadata.ModelType == typeof(WidgetId))
                {
                    return(Mock.Of <IModelBinder>());
                }

                return(null);
            }));

            var factory = new ModelBinderFactory(metadataProvider, options);

            var context = new ModelBinderFactoryContext()
            {
                Metadata = metadataProvider.GetMetadataForType(typeof(Widget)),
            };

            // Act
            var result = factory.CreateBinder(context);

            // Assert
            Assert.NotNull(result);
        }
        public void CreateBinder_Caches_WhenTokenIsNotNull()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = new TestOptionsManager <MvcOptions>();

            options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(c =>
            {
                Assert.Equal(typeof(Employee), c.Metadata.ModelType);
                return(Mock.Of <IModelBinder>());
            }));

            var factory = new ModelBinderFactory(metadataProvider, options);

            var context = new ModelBinderFactoryContext()
            {
                Metadata   = metadataProvider.GetMetadataForType(typeof(Employee)),
                CacheToken = new object(),
            };

            // Act
            var result1 = factory.CreateBinder(context);
            var result2 = factory.CreateBinder(context);

            // Assert
            Assert.Same(result1, result2);
        }
        public void CreateBinder_CreatesNoOpBinder_WhenPropertyDoesntHaveABinder()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            // There isn't a provider that can handle WidgetId.
            var options = new TestOptionsManager <MvcOptions>();

            options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(c =>
            {
                if (c.Metadata.ModelType == typeof(Widget))
                {
                    Assert.NotNull(c.CreateBinder(c.Metadata.Properties[nameof(Widget.Id)]));
                    return(Mock.Of <IModelBinder>());
                }

                return(null);
            }));

            var factory = new ModelBinderFactory(metadataProvider, options);

            var context = new ModelBinderFactoryContext()
            {
                Metadata = metadataProvider.GetMetadataForType(typeof(Widget)),
            };

            // Act
            var result = factory.CreateBinder(context);

            // Assert
            Assert.NotNull(result);
        }
Пример #5
0
        public void CreateBinder_Caches_NonRootNodes_WhenNonRootNodeReturnsNull()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = Options.Create(new MvcOptions());

            IModelBinder inner = null;

            var widgetProvider = new TestModelBinderProvider(c =>
            {
                if (c.Metadata.ModelType == typeof(Widget))
                {
                    var binder = c.CreateBinder(c.Metadata.Properties[nameof(Widget.Id)]);
                    Assert.IsType <NoOpBinder>(binder);
                    if (inner == null)
                    {
                        inner = binder;
                    }
                    else
                    {
                        Assert.Same(inner, binder);
                    }

                    return(Mock.Of <IModelBinder>());
                }

                return(null);
            });

            var widgetIdProvider = new TestModelBinderProvider(c =>
            {
                Assert.Equal(typeof(WidgetId), c.Metadata.ModelType);
                return(null);
            });

            options.Value.ModelBinderProviders.Add(widgetProvider);
            options.Value.ModelBinderProviders.Add(widgetIdProvider);

            var factory = new ModelBinderFactory(
                metadataProvider,
                options,
                GetServices());

            var context = new ModelBinderFactoryContext()
            {
                Metadata   = metadataProvider.GetMetadataForType(typeof(Widget)),
                CacheToken = null, // We want the outermost provider to run twice.
            };

            // Act
            var result1 = factory.CreateBinder(context);
            var result2 = factory.CreateBinder(context);

            // Assert
            Assert.NotSame(result1, result2);

            Assert.Equal(2, widgetProvider.SuccessCount);
            Assert.Equal(0, widgetIdProvider.SuccessCount);
        }
        public void CreateBinder_Caches_NonRootNodes_FixesUpPlaceholderBinder()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = new TestOptionsManager <MvcOptions>();

            IModelBinder inner      = null;
            IModelBinder innerInner = null;

            var widgetProvider = new TestModelBinderProvider(c =>
            {
                if (c.Metadata.ModelType == typeof(Widget))
                {
                    inner = c.CreateBinder(c.Metadata.Properties[nameof(Widget.Id)]);
                    return(Mock.Of <IModelBinder>());
                }

                return(null);
            });

            var widgetIdProvider = new TestModelBinderProvider(c =>
            {
                Assert.Equal(typeof(WidgetId), c.Metadata.ModelType);
                innerInner = c.CreateBinder(c.Metadata);
                return(null);
            });

            options.Value.ModelBinderProviders.Add(widgetProvider);
            options.Value.ModelBinderProviders.Add(widgetIdProvider);

            var factory = new ModelBinderFactory(metadataProvider, options);

            var context = new ModelBinderFactoryContext()
            {
                Metadata   = metadataProvider.GetMetadataForType(typeof(Widget)),
                CacheToken = null,
            };

            // Act 1
            var result1 = factory.CreateBinder(context);

            context.Metadata   = context.Metadata.Properties[nameof(Widget.Id)];
            context.CacheToken = context.Metadata;

            // Act 2
            var result2 = factory.CreateBinder(context);

            // Assert
            Assert.Same(inner, result2);
            Assert.NotSame(inner, innerInner);

            var placeholder = Assert.IsType <PlaceholderBinder>(innerInner);

            Assert.IsType <NoOpBinder>(placeholder.Inner);

            Assert.Equal(1, widgetProvider.SuccessCount);
            Assert.Equal(0, widgetIdProvider.SuccessCount);
        }
Пример #7
0
        public void CreateBinder_Caches_NonRootNodes_UsesModelMetadataAsToken()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = Options.Create(new MvcOptions());

            IModelBinder inner = null;

            var widgetProvider = new TestModelBinderProvider(c =>
            {
                if (c.Metadata.ModelType == typeof(Widget))
                {
                    inner = c.CreateBinder(c.Metadata.Properties[nameof(Widget.Id)]);
                    return(Mock.Of <IModelBinder>());
                }

                return(null);
            });

            var widgetIdProvider = new TestModelBinderProvider(c =>
            {
                Assert.Equal(typeof(WidgetId), c.Metadata.ModelType);
                return(Mock.Of <IModelBinder>());
            });

            options.Value.ModelBinderProviders.Add(widgetProvider);
            options.Value.ModelBinderProviders.Add(widgetIdProvider);

            var factory = new ModelBinderFactory(
                metadataProvider,
                options,
                GetServices());

            var context = new ModelBinderFactoryContext()
            {
                Metadata   = metadataProvider.GetMetadataForType(typeof(Widget)),
                CacheToken = null,
            };

            // Act 1
            var result1 = factory.CreateBinder(context);

            context.Metadata   = context.Metadata.Properties[nameof(Widget.Id)];
            context.CacheToken = context.Metadata;

            // Act 2
            var result2 = factory.CreateBinder(context);

            // Assert
            Assert.Same(inner, result2);
            Assert.Equal(1, widgetProvider.SuccessCount);
            Assert.Equal(1, widgetIdProvider.SuccessCount);
        }
Пример #8
0
            public DefaultModelBinderProviderContext(
                ModelBinderFactory factory,
                ModelBinderFactoryContext factoryContext)
            {
                _factory    = factory;
                Metadata    = factoryContext.Metadata;
                BindingInfo = factoryContext.BindingInfo;

                MetadataProvider = _factory._metadataProvider;
                Stack            = new List <KeyValuePair <Key, PlaceholderBinder> >();
            }
Пример #9
0
            private DefaultModelBinderProviderContext(
                DefaultModelBinderProviderContext parent,
                ModelMetadata metadata,
                BindingInfo bindingInfo)
            {
                Metadata = metadata;

                _factory         = parent._factory;
                MetadataProvider = parent.MetadataProvider;
                Visited          = parent.Visited;
                BindingInfo      = bindingInfo;
            }
Пример #10
0
        public void CreateBinder_PassesExpectedBindingInfo(
            BindingInfo parameterBindingInfo,
            BindingMetadata bindingMetadata,
            BindingInfo expectedInfo)
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            metadataProvider.ForType <Employee>().BindingDetails(binding =>
            {
                binding.BinderModelName = bindingMetadata.BinderModelName;
                binding.BinderType      = bindingMetadata.BinderType;
                binding.BindingSource   = bindingMetadata.BindingSource;
                if (bindingMetadata.PropertyFilterProvider != null)
                {
                    binding.PropertyFilterProvider = bindingMetadata.PropertyFilterProvider;
                }
            });

            var modelBinder         = Mock.Of <IModelBinder>();
            var modelBinderProvider = new TestModelBinderProvider(context =>
            {
                Assert.Equal(typeof(Employee), context.Metadata.ModelType);

                Assert.NotNull(context.BindingInfo);
                Assert.Equal(expectedInfo.BinderModelName, context.BindingInfo.BinderModelName, StringComparer.Ordinal);
                Assert.Equal(expectedInfo.BinderType, context.BindingInfo.BinderType);
                Assert.Equal(expectedInfo.BindingSource, context.BindingInfo.BindingSource);
                Assert.Same(expectedInfo.PropertyFilterProvider, context.BindingInfo.PropertyFilterProvider);

                return(modelBinder);
            });

            var options = Options.Create(new MvcOptions());

            options.Value.ModelBinderProviders.Insert(0, modelBinderProvider);

            var factory = new ModelBinderFactory(
                metadataProvider,
                options,
                GetServices());
            var factoryContext = new ModelBinderFactoryContext
            {
                BindingInfo = parameterBindingInfo,
                Metadata    = metadataProvider.GetMetadataForType(typeof(Employee)),
            };

            // Act & Assert
            var result = factory.CreateBinder(factoryContext);

            // Confirm our IModelBinderProvider was called.
            Assert.Same(modelBinder, result);
        }
Пример #11
0
        public void CreateBinder_Throws_WhenNoProviders()
        {
            // Arrange
            var expected = $"'{typeof(MvcOptions).FullName}.{nameof(MvcOptions.ModelBinderProviders)}' must not be " +
                           $"empty. At least one '{typeof(IModelBinderProvider).FullName}' is required to model bind.";
            var metadataProvider = new TestModelMetadataProvider();
            var options          = Options.Create(new MvcOptions());
            var factory          = new ModelBinderFactory(metadataProvider, options);
            var context          = new ModelBinderFactoryContext()
            {
                Metadata = metadataProvider.GetMetadataForType(typeof(string)),
            };

            // Act & Assert
            var exception = Assert.Throws <InvalidOperationException>(() => factory.CreateBinder(context));

            Assert.Equal(expected, exception.Message);
        }
Пример #12
0
            private DefaultModelBinderProviderContext(
                DefaultModelBinderProviderContext parent,
                ModelMetadata metadata)
            {
                Metadata = metadata;

                _factory         = parent._factory;
                MetadataProvider = parent.MetadataProvider;
                Visited          = parent.Visited;

                BindingInfo = new BindingInfo()
                {
                    BinderModelName        = metadata.BinderModelName,
                    BinderType             = metadata.BinderType,
                    BindingSource          = metadata.BindingSource,
                    PropertyFilterProvider = metadata.PropertyFilterProvider,
                };
            }
Пример #13
0
            public DefaultModelBinderProviderContext(
                ModelBinderFactory factory,
                ModelBinderFactoryContext factoryContext)
            {
                _factory    = factory;
                Metadata    = factoryContext.Metadata;
                BindingInfo = new BindingInfo
                {
                    BinderModelName        = factoryContext.BindingInfo?.BinderModelName ?? Metadata.BinderModelName,
                    BinderType             = factoryContext.BindingInfo?.BinderType ?? Metadata.BinderType,
                    BindingSource          = factoryContext.BindingInfo?.BindingSource ?? Metadata.BindingSource,
                    PropertyFilterProvider =
                        factoryContext.BindingInfo?.PropertyFilterProvider ?? Metadata.PropertyFilterProvider,
                };

                MetadataProvider = _factory._metadataProvider;
                Visited          = new Dictionary <Key, IModelBinder>();
            }
        public void CreateBinder_Throws_WhenBinderNotCreated()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();
            var options          = new TestOptionsManager <MvcOptions>();
            var factory          = new ModelBinderFactory(metadataProvider, options);

            var context = new ModelBinderFactoryContext()
            {
                Metadata = metadataProvider.GetMetadataForType(typeof(string)),
            };

            // Act
            var exception = Assert.Throws <InvalidOperationException>(() => factory.CreateBinder(context));

            // Assert
            Assert.Equal(
                $"Could not create a model binder for model object of type '{typeof(string).FullName}'.",
                exception.Message);
        }
Пример #15
0
        public void CreateBinder_CreatesNoOpBinder_WhenPropertyBindingIsNotAllowed()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            metadataProvider
            .ForProperty <Widget>(nameof(Widget.Id))
            .BindingDetails(m => m.IsBindingAllowed = false);

            var modelBinder = new ByteArrayModelBinder(NullLoggerFactory.Instance);

            var options = Options.Create(new MvcOptions());

            options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(c =>
            {
                if (c.Metadata.ModelType == typeof(WidgetId))
                {
                    return(modelBinder);
                }

                return(null);
            }));

            var factory = new ModelBinderFactory(
                metadataProvider,
                options,
                GetServices());

            var context = new ModelBinderFactoryContext()
            {
                Metadata = metadataProvider.GetMetadataForProperty(typeof(Widget), nameof(Widget.Id)),
            };

            // Act
            var result = factory.CreateBinder(context);

            // Assert
            Assert.NotNull(result);
            Assert.IsType <NoOpBinder>(result);
        }
Пример #16
0
            public DefaultModelBinderProviderContext(
                ModelBinderFactory factory,
                ModelBinderFactoryContext factoryContext)
            {
                _factory = factory;
                Metadata = factoryContext.Metadata;
                BindingInfo bindingInfo;
                if (factoryContext.BindingInfo != null)
                {
                    bindingInfo = new BindingInfo(factoryContext.BindingInfo);
                }
                else
                {
                    bindingInfo = new BindingInfo();
                }

                bindingInfo.TryApplyBindingInfo(Metadata);
                BindingInfo = bindingInfo;

                MetadataProvider = _factory._metadataProvider;
                Visited = new Dictionary<Key, IModelBinder?>();
            }
Пример #17
0
        public void CreateBinder_BreaksCycles()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var callCount = 0;

            var options = Options.Create(new MvcOptions());

            options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(c =>
            {
                var currentCallCount = ++callCount;
                Assert.Equal(typeof(Employee), c.Metadata.ModelType);
                var binder = c.CreateBinder(c.Metadata.Properties[nameof(Employee.Manager)]);

                if (currentCallCount == 2)
                {
                    Assert.IsType <PlaceholderBinder>(binder);
                }

                return(Mock.Of <IModelBinder>());
            }));

            var factory = new ModelBinderFactory(
                metadataProvider,
                options,
                GetServices());

            var context = new ModelBinderFactoryContext()
            {
                Metadata = metadataProvider.GetMetadataForType(typeof(Employee)),
            };

            // Act
            var result = factory.CreateBinder(context);

            // Assert
            Assert.NotNull(result);
        }
Пример #18
0
        public void CreateBinder_Throws_WhenBinderNotCreated()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();
            var options          = Options.Create(new MvcOptions());

            options.Value.ModelBinderProviders.Add(new TestModelBinderProvider(_ => null));

            var factory = new ModelBinderFactory(
                metadataProvider,
                options,
                GetServices());
            var context = new ModelBinderFactoryContext()
            {
                Metadata = metadataProvider.GetMetadataForType(typeof(string)),
            };

            // Act & Assert
            var exception = Assert.Throws <InvalidOperationException>(() => factory.CreateBinder(context));

            Assert.Equal(
                $"Could not create a model binder for model object of type '{typeof(string).FullName}'.",
                exception.Message);
        }