예제 #1
0
        public void GetModelBindingContext_UsesBindAttributeOnType_IfNoBindAttributeOnParameter_ForPrefix()
        {
            // Arrange
            var type          = typeof(ControllerActionArgumentBinderTests);
            var methodInfo    = type.GetMethod("ParameterWithNoBindAttribute");
            var actionContext = new ActionContext(new RouteContext(Mock.Of <HttpContext>()),
                                                  Mock.Of <ActionDescriptor>());

            var metadataProvider = new DataAnnotationsModelMetadataProvider();
            var modelMetadata    = metadataProvider.GetMetadataForParameter(modelAccessor: null,
                                                                            methodInfo: methodInfo,
                                                                            parameterName: "parameter");

            var actionBindingContext = new ActionBindingContext(actionContext,
                                                                Mock.Of <IModelMetadataProvider>(),
                                                                Mock.Of <IModelBinder>(),
                                                                Mock.Of <IValueProvider>(),
                                                                Mock.Of <IInputFormatterSelector>(),
                                                                Mock.Of <IModelValidatorProvider>());
            // Act
            var context = DefaultControllerActionArgumentBinder.GetModelBindingContext(
                modelMetadata, actionBindingContext, Mock.Of <OperationBindingContext>());

            // Assert
            Assert.Equal("TypePrefix", context.ModelName);
        }
예제 #2
0
        public void GetModelBindingContext_ModelBindingContextIsNotSet_ForTypes(
            string actionMethodName, bool expectedFallToEmptyPrefix, string expectedModelName)
        {
            // Arrange
            var type       = typeof(ControllerActionArgumentBinderTests);
            var methodInfo = type.GetMethod(actionMethodName);

            var actionContext = new ActionContext(
                new RouteContext(Mock.Of <HttpContext>()),
                Mock.Of <ActionDescriptor>());

            var metadataProvider = new DataAnnotationsModelMetadataProvider();
            var modelMetadata    = metadataProvider.GetMetadataForParameter(modelAccessor: null,
                                                                            methodInfo: methodInfo,
                                                                            parameterName: "parameter1");

            // Act
            var context = DefaultControllerActionArgumentBinder.GetModelBindingContext(
                modelMetadata,
                actionContext,
                Mock.Of <OperationBindingContext>());

            // Assert
            Assert.Equal(expectedFallToEmptyPrefix, context.FallbackToEmptyPrefix);
            Assert.Equal(expectedModelName, context.ModelName);
        }
예제 #3
0
        public async Task GetActionArgumentsAsync_AddsActionArguments_IfBinderReturnsTrue()
        {
            // Arrange
            Func <object, int> method = foo => 1;
            var actionDescriptor      = new ControllerActionDescriptor
            {
                MethodInfo = method.Method,
                Parameters = new List <ParameterDescriptor>
                {
                    new ParameterDescriptor
                    {
                        Name          = "foo",
                        ParameterType = typeof(string),
                    }
                }
            };
            var value            = "Hello world";
            var binder           = new Mock <IModelBinder>();
            var metadataProvider = new EmptyModelMetadataProvider();

            binder.Setup(b => b.BindModelAsync(It.IsAny <ModelBindingContext>()))
            .Callback((ModelBindingContext context) =>
            {
                context.ModelMetadata = metadataProvider.GetMetadataForType(modelAccessor: null,
                                                                            modelType: typeof(string));
                context.Model = value;
            })
            .Returns(Task.FromResult(result: true));
            var actionContext = new ActionContext(new RouteContext(Mock.Of <HttpContext>()),
                                                  actionDescriptor);

            actionContext.Controller = Mock.Of <object>();
            var bindingContext = new ActionBindingContext(actionContext,
                                                          metadataProvider,
                                                          binder.Object,
                                                          Mock.Of <IValueProvider>(),
                                                          Mock.Of <IInputFormatterSelector>(),
                                                          Mock.Of <IModelValidatorProvider>());

            var actionBindingContextProvider = new Mock <IActionBindingContextProvider>();

            actionBindingContextProvider.Setup(p => p.GetActionBindingContextAsync(It.IsAny <ActionContext>()))
            .Returns(Task.FromResult(bindingContext));

            var invoker = new DefaultControllerActionArgumentBinder(
                actionBindingContextProvider.Object);

            // Act
            var result = await invoker.GetActionArgumentsAsync(actionContext);

            // Assert
            Assert.Equal(1, result.Count);
            Assert.Equal(value, result["foo"]);
        }
        public async Task BindParameter_WithEmptyData_AndPerTypeMessage_AddsGivenMessage(Type parameterType)
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            metadataProvider
            .ForType(parameterType)
            .BindingDetails((Action <ModelBinding.Metadata.BindingMetadata>)(binding =>
            {
                // A real details provider could customize message based on BindingMetadataProviderContext.
                binding.ModelBindingMessageProvider.ValueMustNotBeNullAccessor =
                    value => $"Hurts when '{ value }' is provided.";
            }));
            var argumentBinder = new DefaultControllerActionArgumentBinder(
                metadataProvider,
                ModelBindingTestHelper.GetObjectValidator());
            var parameter = new ParameterDescriptor
            {
                Name        = "Parameter1",
                BindingInfo = new BindingInfo(),

                ParameterType = parameterType
            };
            var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
            {
                request.QueryString = QueryString.Create("Parameter1", string.Empty);
            });
            var modelState = new ModelStateDictionary();

            // Act
            var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);

            // Assert
            // ModelBindingResult
            Assert.False(modelBindingResult.IsModelSet);

            // Model
            Assert.Null(modelBindingResult.Model);

            // ModelState
            Assert.False(modelState.IsValid);
            var key = Assert.Single(modelState.Keys);

            Assert.Equal("Parameter1", key);
            Assert.Equal(string.Empty, modelState[key].AttemptedValue);
            Assert.Equal(string.Empty, modelState[key].RawValue);
            var error = Assert.Single(modelState[key].Errors);

            Assert.Equal("Hurts when '' is provided.", error.ErrorMessage, StringComparer.Ordinal);
            Assert.Null(error.Exception);
        }
        public async Task Parameters_WithMultipleFromBody_Throw()
        {
            // Arrange
            var actionDescriptor = new ControllerActionDescriptor
            {
                MethodInfo = typeof(TestController).GetMethod("ActionWithTwoBodyParam"),
                Parameters = new List <ParameterDescriptor>
                {
                    new ParameterDescriptor
                    {
                        Name          = "bodyParam",
                        ParameterType = typeof(Person),
                    },
                    new ParameterDescriptor
                    {
                        Name          = "bodyParam1",
                        ParameterType = typeof(Person),
                    }
                }
            };

            var binder           = new Mock <IModelBinder>();
            var metadataProvider = new DataAnnotationsModelMetadataProvider();
            var actionContext    = new ActionContext(new RouteContext(Mock.Of <HttpContext>()),
                                                     actionDescriptor);

            actionContext.Controller = Mock.Of <object>();
            var bindingContext = new ActionBindingContext(actionContext,
                                                          metadataProvider,
                                                          Mock.Of <IModelBinder>(),
                                                          Mock.Of <IValueProvider>(),
                                                          Mock.Of <IInputFormatterSelector>(),
                                                          Mock.Of <IModelValidatorProvider>());

            var actionBindingContextProvider = new Mock <IActionBindingContextProvider>();

            actionBindingContextProvider.Setup(p => p.GetActionBindingContextAsync(It.IsAny <ActionContext>()))
            .Returns(Task.FromResult(bindingContext));

            var invoker = new DefaultControllerActionArgumentBinder(
                actionBindingContextProvider.Object);

            // Act
            var ex = await Assert.ThrowsAsync <InvalidOperationException>(
                () => invoker.GetActionArgumentsAsync(actionContext));

            // Assert
            Assert.Equal("More than one parameter is bound to the HTTP request's content.",
                         ex.Message);
        }
예제 #6
0
        public async Task KeyValuePairModelBinder_SimpleTypes_WithNoValue_AndCustomizedMessage_AddsGivenMessage()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();

            metadataProvider
            .ForType(typeof(KeyValuePair <string, int>))
            .BindingDetails((System.Action <ModelBinding.Metadata.BindingMetadata>)(binding =>
            {
                // A real details provider could customize message based on BindingMetadataProviderContext.
                binding.ModelBindingMessageProvider.MissingKeyOrValueAccessor = () => $"Hurts when nothing is provided.";
            }));
            var argumentBinder = new DefaultControllerActionArgumentBinder(
                metadataProvider,
                ModelBindingTestHelper.GetObjectValidator());

            var parameter = new ParameterDescriptor
            {
                Name          = "parameter",
                ParameterType = typeof(KeyValuePair <string, int>)
            };
            var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
            {
                request.QueryString = new QueryString("?parameter.Key=10");
            });
            var modelState = new ModelStateDictionary();

            // Act
            var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);

            // Assert
            Assert.False(modelBindingResult.IsModelSet);
            Assert.Equal(2, modelState.Count);

            Assert.False(modelState.IsValid);
            Assert.Equal(1, modelState.ErrorCount);

            var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter.Key").Value;

            Assert.Empty(entry.Errors);
            Assert.Equal("10", entry.AttemptedValue);
            Assert.Equal("10", entry.RawValue);

            entry = Assert.Single(modelState, kvp => kvp.Key == "parameter.Value").Value;
            var error = Assert.Single(entry.Errors);

            Assert.Null(error.Exception);
            Assert.Equal("Hurts when nothing is provided.", error.ErrorMessage);
        }
예제 #7
0
        public async Task GetActionArgumentsAsync_DoesNotAddActionArguments_IfBinderReturnsFalse()
        {
            // Arrange
            Func <object, int> method = foo => 1;
            var actionDescriptor      = new ControllerActionDescriptor
            {
                MethodInfo = method.Method,
                Parameters = new List <ParameterDescriptor>
                {
                    new ParameterDescriptor
                    {
                        Name          = "foo",
                        ParameterType = typeof(object),
                    }
                }
            };

            var binder = new Mock <IModelBinder>();

            binder
            .Setup(b => b.BindModelAsync(It.IsAny <ModelBindingContext>()))
            .Callback <ModelBindingContext>(c =>
            {
                // This value won't go into the arguments, because we return false.
                c.Model = "Hello";
            })
            .Returns(Task.FromResult(result: false));

            var actionContext = new ActionContext(new RouteContext(Mock.Of <HttpContext>()), actionDescriptor);

            var actionBindingContext = new ActionBindingContext()
            {
                ModelBinder = binder.Object,
            };

            var inputFormattersProvider = new Mock <IInputFormattersProvider>();

            inputFormattersProvider
            .SetupGet(o => o.InputFormatters)
            .Returns(new List <IInputFormatter>());

            var invoker = new DefaultControllerActionArgumentBinder(new DataAnnotationsModelMetadataProvider());

            // Act
            var result = await invoker.GetActionArgumentsAsync(actionContext, actionBindingContext);

            // Assert
            Assert.Empty(result);
        }
예제 #8
0
        public async Task GetActionArgumentsAsync_DoesNotAddActionArguments_IfBinderReturnsFalse()
        {
            // Arrange
            Func <object, int> method = foo => 1;
            var actionDescriptor      = new ControllerActionDescriptor
            {
                MethodInfo = method.Method,
                Parameters = new List <ParameterDescriptor>
                {
                    new ParameterDescriptor
                    {
                        Name          = "foo",
                        ParameterType = typeof(object),
                    }
                }
            };
            var binder = new Mock <IModelBinder>();

            binder.Setup(b => b.BindModelAsync(It.IsAny <ModelBindingContext>()))
            .Returns(Task.FromResult(result: false));
            var actionContext = new ActionContext(new RouteContext(Mock.Of <HttpContext>()),
                                                  actionDescriptor);

            actionContext.Controller = Mock.Of <object>();
            var bindingContext = new ActionBindingContext(actionContext,
                                                          Mock.Of <IModelMetadataProvider>(),
                                                          binder.Object,
                                                          Mock.Of <IValueProvider>(),
                                                          Mock.Of <IInputFormatterSelector>(),
                                                          Mock.Of <IModelValidatorProvider>());
            var inputFormattersProvider = new Mock <IInputFormattersProvider>();

            inputFormattersProvider.SetupGet(o => o.InputFormatters)
            .Returns(new List <IInputFormatter>());
            var actionBindingContextProvider = new Mock <IActionBindingContextProvider>();

            actionBindingContextProvider.Setup(p => p.GetActionBindingContextAsync(It.IsAny <ActionContext>()))
            .Returns(Task.FromResult(bindingContext));

            var invoker = new DefaultControllerActionArgumentBinder(
                actionBindingContextProvider.Object);

            // Act
            var result = await invoker.GetActionArgumentsAsync(actionContext);

            // Assert
            Assert.Empty(result);
        }
예제 #9
0
        public void GetModelBindingContext_ReturnsOnlyIncludedProperties_UsingBindAttributeInclude()
        {
            // Arrange
            var actionContext = new ActionContext(
                new RouteContext(Mock.Of <HttpContext>()),
                Mock.Of <ActionDescriptor>());

            var metadataProvider = new DataAnnotationsModelMetadataProvider();
            var modelMetadata    = metadataProvider.GetMetadataForType(
                modelAccessor: null, modelType: typeof(TypeWithIncludedPropertiesUsingBindAttribute));

            var actionBindingContext = new ActionBindingContext();

            // Act
            var context = DefaultControllerActionArgumentBinder.GetModelBindingContext(
                modelMetadata,
                actionContext,
                Mock.Of <OperationBindingContext>());

            // Assert
            Assert.True(context.PropertyFilter(context, "IncludedExplicitly1"));
            Assert.True(context.PropertyFilter(context, "IncludedExplicitly2"));
        }
        public async Task KeyValuePairModelBinder_SimpleTypes_WithNoKey_AndCustomizedMessage_AddsGivenMessage()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();
            metadataProvider
                .ForType(typeof(KeyValuePair<string, int>))
                .BindingDetails((System.Action<ModelBinding.Metadata.BindingMetadata>)(binding =>
                {
                    // A real details provider could customize message based on BindingMetadataProviderContext.
                    binding.ModelBindingMessageProvider.MissingKeyOrValueAccessor = () => $"Hurts when nothing is provided.";
                }));

            var argumentBinder = new DefaultControllerActionArgumentBinder(
                metadataProvider,
                ModelBindingTestHelper.GetObjectValidator());
            var parameter = new ParameterDescriptor
            {
                Name = "parameter",
                ParameterType = typeof(KeyValuePair<string, int>)
            };
            var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
            {
                request.QueryString = new QueryString("?parameter.Value=10");
            });
            var modelState = new ModelStateDictionary();

            // Act
            var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);

            // Assert
            Assert.False(modelBindingResult.IsModelSet);
            Assert.Equal(2, modelState.Count);

            Assert.False(modelState.IsValid);
            Assert.Equal(1, modelState.ErrorCount);

            var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter.Key").Value;
            var error = Assert.Single(entry.Errors);
            Assert.Null(error.Exception);
            Assert.Equal("Hurts when nothing is provided.", error.ErrorMessage);

            entry = Assert.Single(modelState, kvp => kvp.Key == "parameter.Value").Value;
            Assert.Empty(entry.Errors);
            Assert.Equal("10", entry.AttemptedValue);
            Assert.Equal("10", entry.RawValue);
        }
        public async Task MutableObjectModelBinder_WithBindRequired_NoData_AndCustomizedMessage_AddsGivenMessage()
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();
            metadataProvider
                .ForType(typeof(Order10))
                .BindingDetails((Action<ModelBinding.Metadata.BindingMetadata>)(binding =>
                {
                    // A real details provider could customize message based on BindingMetadataProviderContext.
                    binding.ModelBindingMessageProvider.MissingBindRequiredValueAccessor =
                        name => $"Hurts when '{ name }' is not provided.";
                }));
            var argumentBinder = new DefaultControllerActionArgumentBinder(
                metadataProvider,
                ModelBindingTestHelper.GetObjectValidator());
            var parameter = new ParameterDescriptor()
            {
                Name = "parameter",
                ParameterType = typeof(Order10)
            };

            // No Data
            var operationContext = ModelBindingTestHelper.GetOperationBindingContext();

            var modelState = new ModelStateDictionary();

            // Act
            var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);

            // Assert
            Assert.True(modelBindingResult.IsModelSet);

            var model = Assert.IsType<Order10>(modelBindingResult.Model);
            Assert.Null(model.Customer);

            Assert.Equal(1, modelState.Count);
            Assert.Equal(1, modelState.ErrorCount);
            Assert.False(modelState.IsValid);

            var entry = Assert.Single(modelState, e => e.Key == "Customer").Value;
            Assert.Null(entry.RawValue);
            Assert.Null(entry.AttemptedValue);
            var error = Assert.Single(modelState["Customer"].Errors);
            Assert.Equal("Hurts when 'Customer' is not provided.", error.ErrorMessage);
        }
        public async Task BindParameter_WithEmptyData_AndPerTypeMessage_AddsGivenMessage(Type parameterType)
        {
            // Arrange
            var metadataProvider = new TestModelMetadataProvider();
            metadataProvider
                .ForType(parameterType)
                .BindingDetails((Action<ModelBinding.Metadata.BindingMetadata>)(binding =>
                {
                    // A real details provider could customize message based on BindingMetadataProviderContext.
                    binding.ModelBindingMessageProvider.ValueMustNotBeNullAccessor =
                        value => $"Hurts when '{ value }' is provided.";
                }));
            var argumentBinder = new DefaultControllerActionArgumentBinder(
                metadataProvider,
                ModelBindingTestHelper.GetObjectValidator());
            var parameter = new ParameterDescriptor
            {
                Name = "Parameter1",
                BindingInfo = new BindingInfo(),

                ParameterType = parameterType
            };
            var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
            {
                request.QueryString = QueryString.Create("Parameter1", string.Empty);
            });
            var modelState = new ModelStateDictionary();

            // Act
            var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);

            // Assert
            // ModelBindingResult
            Assert.False(modelBindingResult.IsModelSet);

            // Model
            Assert.Null(modelBindingResult.Model);

            // ModelState
            Assert.False(modelState.IsValid);
            var key = Assert.Single(modelState.Keys);
            Assert.Equal("Parameter1", key);
            Assert.Equal(string.Empty, modelState[key].AttemptedValue);
            Assert.Equal(string.Empty, modelState[key].RawValue);
            var error = Assert.Single(modelState[key].Errors);
            Assert.Equal("Hurts when '' is provided.", error.ErrorMessage, StringComparer.Ordinal);
            Assert.Null(error.Exception);
        }