Example #1
0
        public async Task BindModelAsync_PassesExpectedBindingInfoAndMetadata_IfPrefixDoesNotMatch(
            BindingInfo parameterBindingInfo,
            string metadataBinderModelName,
            string parameterName,
            string expectedModelName)
        {
            // Arrange
            var binderExecuted   = false;
            var metadataProvider = new TestModelMetadataProvider();

            metadataProvider.ForType <Person>().BindingDetails(binding =>
            {
                binding.BinderModelName = metadataBinderModelName;
            });

            var metadata    = metadataProvider.GetMetadataForType(typeof(Person));
            var modelBinder = new Mock <IModelBinder>();

            modelBinder
            .Setup(b => b.BindModelAsync(It.IsAny <ModelBindingContext>()))
            .Callback((ModelBindingContext context) =>
            {
                Assert.Equal(expectedModelName, context.ModelName, StringComparer.Ordinal);
            })
            .Returns(Task.CompletedTask);

            var parameterDescriptor = new ParameterDescriptor
            {
                BindingInfo   = parameterBindingInfo,
                Name          = parameterName,
                ParameterType = typeof(Person),
            };

            var factory = new Mock <IModelBinderFactory>(MockBehavior.Strict);

            factory
            .Setup(f => f.CreateBinder(It.IsAny <ModelBinderFactoryContext>()))
            .Callback((ModelBinderFactoryContext context) =>
            {
                binderExecuted = true;
                // Confirm expected data is passed through to ModelBindingFactory.
                Assert.Same(parameterDescriptor.BindingInfo, context.BindingInfo);
                Assert.Same(parameterDescriptor, context.CacheToken);
                Assert.Equal(metadata, context.Metadata);
            })
            .Returns(modelBinder.Object);

            var parameterBinder = new ParameterBinder(
                metadataProvider,
                factory.Object,
                Mock.Of <IObjectModelValidator>(),
                _optionsAccessor,
                NullLoggerFactory.Instance);

            var controllerContext = GetControllerContext();

            // Act & Assert
            await parameterBinder.BindModelAsync(controllerContext, new SimpleValueProvider(), parameterDescriptor);

            Assert.True(binderExecuted);
        }
Example #2
0
        public async Task BindModelAsync_ForOverlappingParametersWithSuppressions_InValid_WithInValidSecondParameter()
        {
            // Arrange
            var parameterDescriptor = new ParameterDescriptor
            {
                Name          = "patchDocument",
                ParameterType = typeof(IJsonPatchDocument),
            };

            var actionContext = GetControllerContext();
            var modelState    = actionContext.ModelState;

            // First ModelState key is not empty to match SimpleTypeModelBinder.
            modelState.SetModelValue("id", "notAGuid", "notAGuid");
            modelState.AddModelError("id", "This is not valid.");

            // Second ModelState key is empty to match BodyModelBinder.
            modelState.AddModelError(string.Empty, "This is also not valid.");

            var modelMetadataProvider = new TestModelMetadataProvider();

            modelMetadataProvider.ForType <IJsonPatchDocument>().ValidationDetails(v => v.ValidateChildren = false);
            var modelMetadata = modelMetadataProvider.GetMetadataForType(typeof(IJsonPatchDocument));

            var parameterBinder = new ParameterBinder(
                modelMetadataProvider,
                Mock.Of <IModelBinderFactory>(),
                new DefaultObjectValidator(
                    modelMetadataProvider,
                    new[] { TestModelValidatorProvider.CreateDefaultProvider() },
                    new MvcOptions()),
                _optionsAccessor,
                NullLoggerFactory.Instance);

            var modelBindingResult = ModelBindingResult.Failed();
            var modelBinder        = CreateMockModelBinder(modelBindingResult);

            // Act
            var result = await parameterBinder.BindModelAsync(
                actionContext,
                modelBinder,
                new SimpleValueProvider(),
                parameterDescriptor,
                modelMetadata,
                value : null);

            // Assert
            Assert.False(result.IsModelSet);
            Assert.False(modelState.IsValid);
            Assert.Collection(
                modelState,
                kvp =>
            {
                Assert.Empty(kvp.Key);
                Assert.Equal(ModelValidationState.Invalid, kvp.Value.ValidationState);
                var error = Assert.Single(kvp.Value.Errors);
                Assert.Equal("This is also not valid.", error.ErrorMessage);
            },
                kvp =>
            {
                Assert.Equal("id", kvp.Key);
                Assert.Equal(ModelValidationState.Invalid, kvp.Value.ValidationState);
                var error = Assert.Single(kvp.Value.Errors);
                Assert.Equal("This is not valid.", error.ErrorMessage);
            });
        }
Example #3
0
        public void CreateBinder_Caches_NonRootNodes_FixesUpPlaceholderBinder()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            var options = Options.Create(new 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,
                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.NotSame(inner, innerInner);

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

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

            Assert.Equal(1, widgetProvider.SuccessCount);
            Assert.Equal(0, widgetIdProvider.SuccessCount);
        }