示例#1
0
    public void CreateBinder_Caches_WhenTokenIsNotNull()
    {
        // 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)),
            CacheToken = new object(),
        };

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

        // Assert
        Assert.Same(result1, result2);
    }
示例#2
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);
    }
示例#3
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);
    }
示例#4
0
    public void CreateBinder_CreatesNoOpBinder_WhenPropertyDoesntHaveABinder()
    {
        // Arrange
        var metadataProvider = new TestModelMetadataProvider();

        // There isn't a provider that can handle WidgetId.
        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>());
            }

            return(null);
        }));

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

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

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

        // Assert
        Assert.NotNull(result);
    }
示例#5
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);
    }
示例#6
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,
            GetServices());
        var context = new ModelBinderFactoryContext()
        {
            Metadata = metadataProvider.GetMetadataForType(typeof(string)),
        };

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

        Assert.Equal(expected, exception.Message);
    }
示例#7
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);
    }
示例#8
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);
    }
示例#9
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);
    }
示例#10
0
        public void CreateBinder_Caches_NonRootNodes_UsesModelMetadataAsToken()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = new TestOptionsManager<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);

            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);
        }
示例#11
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();

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

                return null;
            }));

            var factory = new ModelBinderFactory(metadataProvider, options);

            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);
        }
示例#12
0
        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);
        }
示例#13
0
        public void CreateBinder_DoesNotCache_WhenTokenIsNull()
        {
            // 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)),
            };

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

            // Assert
            Assert.NotSame(result1, result2);
        }
示例#14
0
        public void CreateBinder_NestedProperties()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            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>();
                }
                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);
        }
示例#15
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 = new TestOptionsManager<MvcOptions>();
            options.Value.ModelBinderProviders.Insert(0, modelBinderProvider);

            var factory = new ModelBinderFactory(metadataProvider, options);
            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);
        }
示例#16
0
        public void CreateBinder_Caches_NonRootNodes_WhenNonRootNodeReturnsNull()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = new TestOptionsManager<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);

            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);
        }
示例#17
0
        public void CreateBinder_BreaksCycles()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var callCount = 0;

            var options = new TestOptionsManager<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);

            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 = 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);
        }