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