Пример #1
0
        public void ExecuteActionAsync_Faults_And_Traces_When_Inner_Faults()
        {
            // Arrange
            InvalidOperationException exception  = new InvalidOperationException("test");
            Mock <IActionFilter>      mockFilter = new Mock <IActionFilter>()
            {
                CallBase = true
            };
            TaskCompletionSource <HttpResponseMessage> tcs = new TaskCompletionSource <HttpResponseMessage>(null);

            tcs.TrySetException(exception);
            mockFilter.Setup(f => f.ExecuteActionFilterAsync(It.IsAny <HttpActionContext>(), It.IsAny <CancellationToken>(),
                                                             It.IsAny <Func <Task <HttpResponseMessage> > >())).Returns(tcs.Task);
            Mock <HttpActionDescriptor> mockActionDescriptor = new Mock <HttpActionDescriptor>()
            {
                CallBase = true
            };

            mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
            mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection <HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
            HttpActionContext  actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
            TestTraceWriter    traceWriter   = new TestTraceWriter();
            ActionFilterTracer tracer        = new ActionFilterTracer(mockFilter.Object, traceWriter);
            Func <Task <HttpResponseMessage> > continuation =
                () => TaskHelpers.FromResult <HttpResponseMessage>(new HttpResponseMessage());

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin, Operation = "ExecuteActionFilterAsync"
                },
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Error)
                {
                    Kind = TraceKind.End, Operation = "ExecuteActionFilterAsync"
                },
            };

            // Act
            Task <HttpResponseMessage> task = ((IActionFilter)tracer).ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);


            // Assert
            Exception thrown = Assert.Throws <InvalidOperationException>(() => task.Wait());

            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
            Assert.Same(exception, traceWriter.Traces[1].Exception);
        }
        public void SetProperty_SettingNullableTypeToNull_RequiredValidatorPresent_PropertySetterThrows_AddsRequiredMessageString()
        {
            // Arrange
            HttpActionContext   context        = ContextUtil.CreateActionContext();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = GetMetadataForObject(new ModelWhosePropertySetterThrows()),
                ModelName     = "foo"
            };

            ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(
                o => o.PropertyName == "Name"
                );
            ModelValidationNode validationNode = new ModelValidationNode(
                propertyMetadata,
                "foo.Name"
                );
            ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(
                null /* model */
                ,
                validationNode
                );
            ModelValidator requiredValidator = context
                                               .GetValidators(propertyMetadata)
                                               .Where(v => v.IsRequired)
                                               .FirstOrDefault();

            TestableMutableObjectModelBinder testableBinder =
                new TestableMutableObjectModelBinder();

            // Act
            testableBinder.SetPropertyPublic(
                context,
                bindingContext,
                propertyMetadata,
                dtoResult,
                requiredValidator
                );

            // Assert
            Assert.False(bindingContext.ModelState.IsValid);
            ModelError modelError = Assert.Single(bindingContext.ModelState["foo.Name"].Errors);

            Assert.Equal(
                "This message comes from the [Required] attribute.",
                modelError.ErrorMessage
                );
        }
Пример #3
0
        public void ExecuteActionFilterAsync_Traces_Executing_And_Executed()
        {
            // Arrange
            Mock <ActionFilterAttribute> mockAttr = new Mock <ActionFilterAttribute>()
            {
                CallBase = true
            };
            Mock <HttpActionDescriptor> mockActionDescriptor = new Mock <HttpActionDescriptor>()
            {
                CallBase = true
            };

            mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
            mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection <HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
            HttpActionContext                  actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
            TestTraceWriter                    traceWriter   = new TestTraceWriter();
            ActionFilterAttributeTracer        tracer        = new ActionFilterAttributeTracer(mockAttr.Object, traceWriter);
            Func <Task <HttpResponseMessage> > continuation  =
                () => TaskHelpers.FromResult <HttpResponseMessage>(new HttpResponseMessage());

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin, Operation = "ActionExecuting"
                },
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.End, Operation = "ActionExecuting"
                },
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin, Operation = "ActionExecuted"
                },
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.End, Operation = "ActionExecuted"
                }
            };

            // Act
            Task <HttpResponseMessage> task = ((IActionFilter)tracer).ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);

            task.Wait();

            // Assert
            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
        }
        public void Validate_DoesNotUseOverridden_GetHashCodeOrEquals()
        {
            // Arrange
            ModelMetadataProvider     metadataProvider = new DataAnnotationsModelMetadataProvider();
            HttpActionContext         actionContext    = ContextUtil.CreateActionContext();
            DefaultBodyModelValidator validator        = new DefaultBodyModelValidator();
            object instance = new[] { new TypeThatOverridesEquals {
                                          Funny = "hehe"
                                      }, new TypeThatOverridesEquals {
                                          Funny = "hehe"
                                      } };

            // Act & Assert
            Assert.DoesNotThrow(
                () => validator.Validate(instance, typeof(TypeThatOverridesEquals[]), metadataProvider, actionContext, String.Empty));
        }
        public void ExcludedTypes_AreNotValidated()
        {
            // Arrange
            ModelMetadataProvider            metadataProvider = new DataAnnotationsModelMetadataProvider();
            HttpActionContext                actionContext    = ContextUtil.CreateActionContext();
            Mock <DefaultBodyModelValidator> mockValidator    = new Mock <DefaultBodyModelValidator>();

            mockValidator.CallBase = true;
            mockValidator.Setup(validator => validator.ShouldValidateType(typeof(Person))).Returns(false);

            // Act
            mockValidator.Object.Validate(new Person(), typeof(Person), metadataProvider, actionContext, string.Empty);

            // Assert
            Assert.True(actionContext.ModelState.IsValid);
        }
        public void ExecuteActionFilterAsync_IfContinuationParameterIsNull_ThrowsException()
        {
            var filter = new TestableActionFilter() as IActionFilter;

            Assert.ThrowsArgumentNull(
                () =>
            {
                filter.ExecuteActionFilterAsync(
                    actionContext: ContextUtil.CreateActionContext(),
                    cancellationToken: CancellationToken.None,
                    continuation: null
                    );
            },
                "continuation"
                );
        }
        public HttpActionSelectorTracerTest()
        {
            _mockActionDescriptor = new Mock <HttpActionDescriptor>()
            {
                CallBase = true
            };
            _mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
            _mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection <HttpParameterDescriptor>(new HttpParameterDescriptor[0]));

            _controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "controller", typeof(ApiController));

            _controllerContext = ContextUtil.CreateControllerContext(request: new HttpRequestMessage());
            _controllerContext.ControllerDescriptor = _controllerDescriptor;

            _actionContext = ContextUtil.CreateActionContext(_controllerContext, actionDescriptor: _mockActionDescriptor.Object);
        }
        public void BindModel_SubBindingSucceeds()
        {
            // Arrange
            Mock <IModelBinder> mockIntBinder    = new Mock <IModelBinder>();
            Mock <IModelBinder> mockStringBinder = new Mock <IModelBinder>();
            ModelBindingContext bindingContext   = new ModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair <int, string>)),
                ModelName     = "someName",
                ValueProvider = new SimpleHttpValueProvider()
            };
            HttpActionContext context = ContextUtil.CreateActionContext();

            context.ControllerContext.Configuration.ServiceResolver.SetServices(typeof(ModelBinderProvider),
                                                                                new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object)
            {
                SuppressPrefixCheck = true
            },
                                                                                new SimpleModelBinderProvider(typeof(string), mockStringBinder.Object)
            {
                SuppressPrefixCheck = true
            });

            mockIntBinder
            .Setup(o => o.BindModel(context, It.IsAny <ModelBindingContext>()))
            .Returns((HttpActionContext cc, ModelBindingContext mbc) =>
            {
                mbc.Model = 42;
                return(true);
            });
            mockStringBinder
            .Setup(o => o.BindModel(context, It.IsAny <ModelBindingContext>()))
            .Returns((HttpActionContext cc, ModelBindingContext mbc) =>
            {
                mbc.Model = "forty-two";
                return(true);
            });
            KeyValuePairModelBinder <int, string> binder = new KeyValuePairModelBinder <int, string>();

            // Act
            bool retVal = binder.BindModel(context, bindingContext);

            // Assert
            Assert.True(retVal);
            Assert.Equal(new KeyValuePair <int, string>(42, "forty-two"), bindingContext.Model);
            Assert.Equal(new[] { "someName.key", "someName.value" }, bindingContext.ValidationNode.ChildNodes.Select(n => n.ModelStateKey).ToArray());
        }
Пример #9
0
        public void BindModel_SuccessfulBind_RunsValidationAndReturnsModel()
        {
            // Arrange
            HttpActionContext actionContext = ContextUtil.CreateActionContext(GetHttpControllerContext());
            bool validationCalled           = false;

            ModelBindingContext bindingContext = new ModelBindingContext
            {
                FallbackToEmptyPrefix = true,
                ModelMetadata         = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName             = "someName",
                //ModelState = executionContext.Controller.ViewData.ModelState,
                //PropertyFilter = _ => true,
                ValueProvider = new SimpleValueProvider
                {
                    { "someName", "dummyValue" }
                }
            };

            Mock <IModelBinder> mockIntBinder = new Mock <IModelBinder>();

            mockIntBinder
            .Setup(o => o.BindModel(actionContext, It.IsAny <ModelBindingContext>()))
            .Returns(
                delegate(HttpActionContext cc, ModelBindingContext mbc)
            {
                Assert.Same(bindingContext.ModelMetadata, mbc.ModelMetadata);
                Assert.Equal("someName", mbc.ModelName);
                Assert.Same(bindingContext.ValueProvider, mbc.ValueProvider);

                mbc.Model = 42;
                mbc.ValidationNode.Validating += delegate { validationCalled = true; };
                return(true);
            });

            //binderProviders.RegisterBinderForType(typeof(int), mockIntBinder.Object, false /* suppressPrefixCheck */);
            IModelBinder shimBinder = new CompositeModelBinder(mockIntBinder.Object);

            // Act
            bool isBound = shimBinder.BindModel(actionContext, bindingContext);

            // Assert
            Assert.True(isBound);
            Assert.Equal(42, bindingContext.Model);
            Assert.True(validationCalled);
            Assert.True(bindingContext.ModelState.IsValid);
        }
Пример #10
0
        public void BindModel()
        {
            // Arrange
            Mock <IValueProvider> mockValueProvider = new Mock <IValueProvider>();

            mockValueProvider.Setup(o => o.ContainsPrefix(It.IsAny <string>())).Returns(true);

            Mock <IModelBinder> mockDtoBinder  = new Mock <IModelBinder>();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = GetMetadataForObject(new Person()),
                ModelName     = "someName",
                ValueProvider = mockValueProvider.Object
            };
            HttpActionContext context = ContextUtil.CreateActionContext();

            context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(ComplexModelDto), mockDtoBinder.Object)
            {
                SuppressPrefixCheck = true
            });

            mockDtoBinder
            .Setup(o => o.BindModel(context, It.IsAny <ModelBindingContext>()))
            .Returns((HttpActionContext cc, ModelBindingContext mbc2) =>
            {
                return(true);    // just return the DTO unchanged
            });

            Mock <TestableMutableObjectModelBinder> mockTestableBinder = new Mock <TestableMutableObjectModelBinder> {
                CallBase = true
            };

            mockTestableBinder.Setup(o => o.EnsureModelPublic(context, bindingContext)).Verifiable();
            mockTestableBinder.Setup(o => o.GetMetadataForPropertiesPublic(context, bindingContext)).Returns(new ModelMetadata[0]).Verifiable();
            TestableMutableObjectModelBinder testableBinder = mockTestableBinder.Object;

            testableBinder.MetadataProvider = new DataAnnotationsModelMetadataProvider();

            // Act
            bool retValue = testableBinder.BindModel(context, bindingContext);

            // Assert
            Assert.True(retValue);
            Assert.IsType <Person>(bindingContext.Model);
            Assert.True(bindingContext.ValidationNode.ValidateAllProperties);
            mockTestableBinder.Verify();
        }
        public void ProcessDto_RequiredFieldMissing_RaisesModelError()
        {
            // Arrange
            ModelWithRequired model             = new ModelWithRequired();
            ModelMetadata     containerMetadata = GetMetadataForObject(model);
            HttpActionContext context           = ContextUtil.CreateActionContext();

            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = containerMetadata,
                ModelName     = "theModel"
            };

            // Set no properties though Age (a non-Nullable struct) and City (a class) properties are required.
            ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties);
            TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder();

            // Act
            testableBinder.ProcessDto(context, bindingContext, dto);

            // Assert
            ModelStateDictionary modelStateDictionary = bindingContext.ModelState;

            Assert.False(modelStateDictionary.IsValid);
            Assert.Equal(2, modelStateDictionary.Count);

            // Check Age error.
            ModelState modelState;

            Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState));
            Assert.Equal(1, modelState.Errors.Count);

            ModelError modelError = modelState.Errors[0];

            Assert.Null(modelError.Exception);
            Assert.NotNull(modelError.ErrorMessage);
            Assert.Equal("The Age field is required.", modelError.ErrorMessage);

            // Check City error.
            Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState));
            Assert.Equal(1, modelState.Errors.Count);

            modelError = modelState.Errors[0];
            Assert.Null(modelError.Exception);
            Assert.NotNull(modelError.ErrorMessage);
            Assert.Equal("The City field is required.", modelError.ErrorMessage);
        }
Пример #12
0
        public void ExecuteBindingAsync_Traces_And_Invokes_Inner()
        {
            // Arrange
            Mock <HttpParameterDescriptor> mockParamDescriptor = new Mock <HttpParameterDescriptor>()
            {
                CallBase = true
            };

            mockParamDescriptor.Setup(d => d.ParameterName).Returns("paramName");
            mockParamDescriptor.Setup(d => d.ParameterType).Returns(typeof(string));
            Mock <HttpParameterBinding> mockBinding = new Mock <HttpParameterBinding>(mockParamDescriptor.Object)
            {
                CallBase = true
            };
            bool innerInvoked = false;

            mockBinding.Setup(
                b =>
                b.ExecuteBindingAsync(It.IsAny <ModelMetadataProvider>(), It.IsAny <HttpActionContext>(),
                                      It.IsAny <CancellationToken>())).Returns(TaskHelpers.Completed()).Callback(() => innerInvoked = true);

            TestTraceWriter            traceWriter      = new TestTraceWriter();
            HttpParameterBindingTracer tracer           = new HttpParameterBindingTracer(mockBinding.Object, traceWriter);
            HttpActionContext          actionContext    = ContextUtil.CreateActionContext();
            ModelMetadataProvider      metadataProvider = new EmptyModelMetadataProvider();

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin, Operation = "ExecuteBindingAsync"
                },
                new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.End, Operation = "ExecuteBindingAsync"
                }
            };

            // Act
            Task task = tracer.ExecuteBindingAsync(metadataProvider, actionContext, CancellationToken.None);

            task.Wait();

            // Assert
            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
            Assert.True(innerInvoked);
        }
        public async Task ExecuteActionFilterAsync_IfContinuationFaulted_InvokesOnActionExecutedAsError()
        {
            // Arrange
            HttpActionContext context = ContextUtil.CreateActionContext();

            Mock <ActionFilterAttribute> filterMock = new Mock <ActionFilterAttribute>()
            {
                CallBase = true,
            };

            var       filter    = (IActionFilter)filterMock.Object;
            Exception exception = new Exception("{ABCC912C-B6D1-4C27-9059-732ABC644A0C}");
            Func <Task <HttpResponseMessage> > continuation = () =>
                                                              TaskHelpers.FromError <HttpResponseMessage>(exception);

            // Act & Assert
            await Assert.ThrowsAsync <Exception>(
                () => filter.ExecuteActionFilterAsync(context, CancellationToken.None, continuation)
                );

            // Assert
            filterMock.Verify(
                f =>
                f.OnActionExecuted(
                    It.Is <HttpActionExecutedContext>(
                        ec =>
                        Object.ReferenceEquals(ec.Exception, exception) &&
                        ec.Response == null &&
                        Object.ReferenceEquals(ec.ActionContext, context)
                        )
                    )
                );

            filterMock.Verify(
                f =>
                f.OnActionExecutedAsync(
                    It.Is <HttpActionExecutedContext>(
                        ec =>
                        Object.ReferenceEquals(ec.Exception, exception) &&
                        ec.Response == null &&
                        Object.ReferenceEquals(ec.ActionContext, context)
                        ),
                    It.IsAny <CancellationToken>()
                    )
                );
        }
Пример #14
0
        public HttpActionInvokerTracerTest()
        {
            UsersController controller = new UsersController();

            _apiController = controller;

            Func <HttpResponseMessage> actionMethod = controller.Get;

            _actionContext = ContextUtil.CreateActionContext(
                ContextUtil.CreateControllerContext(instance: _apiController),
                new ReflectedHttpActionDescriptor {
                MethodInfo = actionMethod.Method
            });
            HttpRequestMessage request = new HttpRequestMessage();

            _actionContext.ControllerContext.Request = request;
        }
        public void SetProperty_SettingNonNullableValueTypeToNull_RequiredValidatorPresent_AddsModelError()
        {
            // Arrange
            HttpActionContext   context        = ContextUtil.CreateActionContext();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = GetMetadataForObject(new Person()),
                ModelName     = "foo"
            };

            ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(
                o => o.PropertyName == "ValueTypeRequired"
                );
            ModelValidationNode validationNode = new ModelValidationNode(
                propertyMetadata,
                "foo.ValueTypeRequired"
                );
            ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(
                null /* model */
                ,
                validationNode
                );
            ModelValidator requiredValidator = context
                                               .GetValidators(propertyMetadata)
                                               .Where(v => v.IsRequired)
                                               .FirstOrDefault();

            TestableMutableObjectModelBinder testableBinder =
                new TestableMutableObjectModelBinder();

            // Act
            testableBinder.SetPropertyPublic(
                context,
                bindingContext,
                propertyMetadata,
                dtoResult,
                requiredValidator
                );

            // Assert
            Assert.False(bindingContext.ModelState.IsValid);
            Assert.Equal(
                "Sample message",
                bindingContext.ModelState["foo.ValueTypeRequired"].Errors[0].ErrorMessage
                );
        }
Пример #16
0
        public void BindModel()
        {
            // Arrange
            Mock <IModelBinder> mockIntBinder = new Mock <IModelBinder>();
            HttpActionContext   context       = ContextUtil.CreateActionContext();

            context.ControllerContext.Configuration.Services.Replace(
                typeof(ModelBinderProvider),
                new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object)
                );

            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(
                    null,
                    typeof(int[])
                    ),
                ModelName     = "someName",
                ValueProvider = new SimpleHttpValueProvider
                {
                    { "someName[0]", "42" },
                    { "someName[1]", "84" }
                }
            };

            mockIntBinder
            .Setup(o => o.BindModel(context, It.IsAny <ModelBindingContext>()))
            .Returns(
                (HttpActionContext ec, ModelBindingContext mbc) =>
            {
                mbc.Model = mbc.ValueProvider
                            .GetValue(mbc.ModelName)
                            .ConvertTo(mbc.ModelType);
                return(true);
            }
                );

            // Act
            bool retVal = new ArrayModelBinder <int>().BindModel(context, bindingContext);

            // Assert
            Assert.True(retVal);

            int[] array = bindingContext.Model as int[];
            Assert.Equal(new[] { 42, 84 }, array);
        }
        public async Task InvokeActionWithActionFilters_ChainsFiltersInOrderFollowedByInnerActionContinuation()
        {
            // Arrange
            HttpActionContext    actionContextInstance = ContextUtil.CreateActionContext();
            List <string>        log = new List <string>();
            Mock <IActionFilter> globalFilterMock = CreateActionFilterMock(
                (ctx, ct, continuation) =>
            {
                log.Add("globalFilter");
                return(continuation());
            }
                );
            Mock <IActionFilter> actionFilterMock = CreateActionFilterMock(
                (ctx, ct, continuation) =>
            {
                log.Add("actionFilter");
                return(continuation());
            }
                );
            Func <Task <HttpResponseMessage> > innerAction = () =>
                                                             Task <HttpResponseMessage> .Factory.StartNew(
                () =>
            {
                log.Add("innerAction");
                return(null);
            }
                );

            var filters = new IActionFilter[] { globalFilterMock.Object, actionFilterMock.Object, };

            // Act
            var result = ActionFilterResult.InvokeActionWithActionFilters(
                actionContextInstance,
                CancellationToken.None,
                filters,
                innerAction
                );

            // Assert
            Assert.NotNull(result);
            await result();

            Assert.Equal(new[] { "globalFilter", "actionFilter", "innerAction" }, log.ToArray());
            globalFilterMock.Verify();
            actionFilterMock.Verify();
        }
        public void ProcessDto_RequiredFieldNull_RaisesModelError()
        {
            // Arrange
            ModelWithRequired model             = new ModelWithRequired();
            ModelMetadata     containerMetadata = GetMetadataForObject(model);
            HttpActionContext context           = ContextUtil.CreateActionContext();

            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = containerMetadata,
                ModelName     = "theModel"
            };

            ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties);
            TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder();

            // Make Age valid and City invalid.
            ModelMetadata propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "Age");

            dto.Results[propertyMetadata] =
                new ComplexModelDtoResult(23, new ModelValidationNode(propertyMetadata, "theModel.Age"));
            propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "City");
            dto.Results[propertyMetadata] =
                new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.City"));

            // Act
            testableBinder.ProcessDto(context, bindingContext, dto);

            // Assert
            ModelStateDictionary modelStateDictionary = bindingContext.ModelState;

            Assert.False(modelStateDictionary.IsValid);
            Assert.Equal(1, modelStateDictionary.Count);

            // Check City error.
            ModelState modelState;

            Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState));
            Assert.Equal(1, modelState.Errors.Count);

            ModelError modelError = modelState.Errors[0];

            Assert.Null(modelError.Exception);
            Assert.NotNull(modelError.ErrorMessage);
            Assert.Equal("The City field is required.", modelError.ErrorMessage);
        }
        public void ProcessDto_BindRequiredFieldMissing_RaisesModelError()
        {
            // Arrange
            ModelWithBindRequired model = new ModelWithBindRequired
            {
                Name = "original value",
                Age  = -20
            };

            ModelMetadata containerMetadata = GetMetadataForObject(model);

            HttpActionContext   context        = ContextUtil.CreateActionContext();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = containerMetadata,
                ModelName     = "theModel"
            };
            ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties);

            ModelMetadata nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name");

            dto.Results[nameProperty] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(nameProperty, ""));

            TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder();

            // Act
            testableBinder.ProcessDto(context, bindingContext, dto);

            // Assert
            ModelStateDictionary modelStateDictionary = bindingContext.ModelState;

            Assert.False(modelStateDictionary.IsValid);
            Assert.Equal(1, modelStateDictionary.Count);

            // Check Age error.
            ModelState modelState;

            Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState));
            Assert.Equal(1, modelState.Errors.Count);

            ModelError modelError = modelState.Errors[0];

            Assert.Null(modelError.Exception);
            Assert.NotNull(modelError.ErrorMessage);
            Assert.Equal("The Age property is required.", modelError.ErrorMessage);
        }
            public BindModel()
            {
                actionContext = ContextUtil.CreateActionContext();

                binder = new PaginationBinder <StubPagination>();

                var data          = new DataAnnotationsModelMetadataProvider();
                var modelMetadata = data.GetMetadataForType(null, typeof(IPagination));

                mockValueProvider = new Mock <IValueProvider>();
                bindingContext    = new ModelBindingContext
                {
                    ModelName     = modelName,
                    ValueProvider = mockValueProvider.Object,
                    ModelMetadata = modelMetadata,
                };
            }
Пример #21
0
        public void ExecuteBindingAsync_Traces_And_Throws_When_Inner_Throws()
        {
            // Arrange
            Mock <HttpParameterDescriptor> mockParamDescriptor = new Mock <HttpParameterDescriptor>()
            {
                CallBase = true
            };

            mockParamDescriptor.Setup(d => d.ParameterName).Returns("paramName");
            mockParamDescriptor.Setup(d => d.ParameterType).Returns(typeof(string));
            Mock <HttpParameterBinding> mockBinding = new Mock <HttpParameterBinding>(mockParamDescriptor.Object)
            {
                CallBase = true
            };
            InvalidOperationException exception = new InvalidOperationException("test");

            mockBinding.Setup(
                b =>
                b.ExecuteBindingAsync(It.IsAny <ModelMetadataProvider>(), It.IsAny <HttpActionContext>(),
                                      It.IsAny <CancellationToken>())).Throws(exception);

            TestTraceWriter            traceWriter      = new TestTraceWriter();
            HttpParameterBindingTracer tracer           = new HttpParameterBindingTracer(mockBinding.Object, traceWriter);
            HttpActionContext          actionContext    = ContextUtil.CreateActionContext();
            ModelMetadataProvider      metadataProvider = new EmptyModelMetadataProvider();

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin, Operation = "ExecuteBindingAsync"
                },
                new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Error)
                {
                    Kind = TraceKind.End, Operation = "ExecuteBindingAsync"
                }
            };

            // Act & Assert
            Exception thrown = Assert.Throws <InvalidOperationException>(() => tracer.ExecuteBindingAsync(metadataProvider, actionContext, CancellationToken.None));

            // Assert
            Assert.Same(exception, thrown);
            Assert.Same(exception, traceWriter.Traces[1].Exception);
            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
        }
Пример #22
0
        public async Task ExecuteActionAsync_Traces_ExecuteActionFilterAsync()
        {
            // Arrange
            HttpResponseMessage  response   = new HttpResponseMessage();
            Mock <IActionFilter> mockFilter = new Mock <IActionFilter>()
            {
                CallBase = true
            };

            mockFilter.Setup(
                f =>
                f.ExecuteActionFilterAsync(It.IsAny <HttpActionContext>(), It.IsAny <CancellationToken>(),
                                           It.IsAny <Func <Task <HttpResponseMessage> > >())).Returns(
                Task.FromResult <HttpResponseMessage>(response));
            Mock <HttpActionDescriptor> mockActionDescriptor = new Mock <HttpActionDescriptor>()
            {
                CallBase = true
            };

            mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
            mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection <HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
            HttpActionContext  actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
            TestTraceWriter    traceWriter   = new TestTraceWriter();
            ActionFilterTracer tracer        = new ActionFilterTracer(mockFilter.Object, traceWriter);
            Func <Task <HttpResponseMessage> > continuation =
                () => Task.FromResult <HttpResponseMessage>(new HttpResponseMessage());

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin, Operation = "ExecuteActionFilterAsync"
                },
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.End, Operation = "ExecuteActionFilterAsync"
                },
            };

            // Act
            var filter = (IActionFilter)tracer;
            await filter.ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);

            // Assert
            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
        }
        public void BindModel_UnsuccessfulBind_SimpleTypeNoFallback_ReturnsNull()
        {
            // Arrange
            HttpActionContext actionContext = ContextUtil.CreateActionContext(
                GetHttpControllerContext()
                );
            Mock <ModelBinderProvider> mockBinderProvider = new Mock <ModelBinderProvider>();

            mockBinderProvider
            .Setup(o => o.GetBinder(It.IsAny <HttpConfiguration>(), It.IsAny <Type>()))
            .Returns((IModelBinder)null)
            .Verifiable();
            List <ModelBinderProvider> binderProviders = new List <ModelBinderProvider>()
            {
                mockBinderProvider.Object
            };
            CompositeModelBinderProvider shimBinderProvider = new CompositeModelBinderProvider(
                binderProviders
                );
            CompositeModelBinder shimBinder = new CompositeModelBinder(
                shimBinderProvider.GetBinder(null, null)
                );

            ModelBindingContext bindingContext = new ModelBindingContext
            {
                FallbackToEmptyPrefix = true,
                ModelMetadata         = new EmptyModelMetadataProvider().GetMetadataForType(
                    null,
                    typeof(int)
                    ),
                //ModelState = executionContext.Controller.ViewData.ModelState
            };

            // Act
            bool isBound = shimBinder.BindModel(actionContext, bindingContext);

            // Assert
            Assert.False(isBound);
            Assert.Null(bindingContext.Model);
            Assert.True(bindingContext.ModelState.IsValid);
            mockBinderProvider.Verify();
            mockBinderProvider.Verify(
                o => o.GetBinder(It.IsAny <HttpConfiguration>(), It.IsAny <Type>()),
                Times.AtMostOnce()
                );
        }
Пример #24
0
        public void NullCheckFailedHandler_ModelStateValid_AddsErrorString()
        {
            // Arrange
            HttpActionContext       context        = ContextUtil.CreateActionContext();
            ModelMetadata           modelMetadata  = GetMetadataForType(typeof(Person));
            ModelValidationNode     validationNode = new ModelValidationNode(modelMetadata, "foo");
            ModelValidatedEventArgs e = new ModelValidatedEventArgs(context, null /* parentNode */);

            // Act
            EventHandler <ModelValidatedEventArgs> handler = MutableObjectModelBinder.CreateNullCheckFailedHandler(modelMetadata, null /* incomingValue */);

            handler(validationNode, e);

            // Assert
            Assert.True(context.ModelState.ContainsKey("foo"));
            Assert.Equal("A value is required.", context.ModelState["foo"].Errors[0].ErrorMessage);
        }
Пример #25
0
        public void BindModel_SimpleCollection()
        {
            // Arrange
            CultureInfo         culture        = CultureInfo.GetCultureInfo("fr-FR");
            Mock <IModelBinder> mockIntBinder  = new Mock <IModelBinder>();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(
                    null,
                    typeof(int)
                    ),
                ModelName     = "someName",
                ValueProvider = new SimpleHttpValueProvider
                {
                    { "someName", new[] { "42", "100", "200" } }
                }
            };
            HttpActionContext context = ContextUtil.CreateActionContext();

            context.ControllerContext.Configuration.Services.Replace(
                typeof(ModelBinderProvider),
                new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object)
                );

            mockIntBinder
            .Setup(o => o.BindModel(context, It.IsAny <ModelBindingContext>()))
            .Returns(
                (HttpActionContext ec, ModelBindingContext mbc) =>
            {
                mbc.Model = mbc.ValueProvider
                            .GetValue(mbc.ModelName)
                            .ConvertTo(mbc.ModelType);
                return(true);
            }
                );

            CollectionModelBinder <int> modelBinder = new CollectionModelBinder <int>();

            // Act
            bool retVal = modelBinder.BindModel(context, bindingContext);

            // Assert
            Assert.True(retVal);
            Assert.Equal(new[] { 42, 100, 200 }, ((List <int>)bindingContext.Model).ToArray());
        }
Пример #26
0
        public async Task ExecuteActionFilterAsync_Faults_And_Traces_When_OnExecuting_Faults()
        {
            // Arrange
            Mock <ActionFilterAttribute> mockAttr = new Mock <ActionFilterAttribute>()
            {
                CallBase = true
            };
            InvalidOperationException exception = new InvalidOperationException("test");

            mockAttr.Setup(a => a.OnActionExecuting(It.IsAny <HttpActionContext>())).Throws(exception);
            Mock <HttpActionDescriptor> mockActionDescriptor = new Mock <HttpActionDescriptor>()
            {
                CallBase = true
            };

            mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
            mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection <HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
            HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
            TestTraceWriter   traceWriter   = new TestTraceWriter();
            IActionFilter     tracer        = new ActionFilterAttributeTracer(mockAttr.Object, traceWriter) as IActionFilter;
            Func <Task <HttpResponseMessage> > continuation =
                () => Task.FromResult <HttpResponseMessage>(new HttpResponseMessage());

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin, Operation = "OnActionExecutingAsync"
                },
                new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Error)
                {
                    Kind = TraceKind.End, Operation = "OnActionExecutingAsync"
                }
            };

            // Act
            Task <HttpResponseMessage> task = tracer.ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);

            // Assert
            Exception thrown = await Assert.ThrowsAsync <InvalidOperationException>(() => task);

            Assert.Same(exception, thrown);
            Assert.Same(exception, traceWriter.Traces[1].Exception);
            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
        }
Пример #27
0
        public void ExecuteAsync_Faults_And_Traces_When_Inner_Faults()
        {
            // Arrange
            InvalidOperationException exception            = new InvalidOperationException();
            TaskCompletionSource <HttpResponseMessage> tcs = new TaskCompletionSource <HttpResponseMessage>();

            tcs.TrySetException(exception);
            Mock <ApiController> mockController = new Mock <ApiController>()
            {
                CallBase = true
            };

            mockController.Setup(b => b.ExecuteAsync(It.IsAny <HttpControllerContext>(), It.IsAny <CancellationToken>())).Returns(tcs.Task);

            HttpRequestMessage    request           = new HttpRequestMessage();
            HttpControllerContext controllerContext = ContextUtil.CreateControllerContext(request: request);

            controllerContext.ControllerDescriptor = _controllerDescriptor;
            controllerContext.Controller           = mockController.Object;

            HttpActionContext actionContext = ContextUtil.CreateActionContext(controllerContext, actionDescriptor: _mockActionDescriptor.Object);

            TestTraceWriter      traceWriter = new TestTraceWriter();
            HttpControllerTracer tracer      = new HttpControllerTracer(request, mockController.Object, traceWriter);

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(actionContext.Request, TraceCategories.ControllersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin
                },
                new TraceRecord(actionContext.Request, TraceCategories.ControllersCategory, TraceLevel.Error)
                {
                    Kind = TraceKind.End
                }
            };

            // Act
            Exception thrown = Assert.Throws <InvalidOperationException>(() => ((IHttpController)tracer).ExecuteAsync(controllerContext, CancellationToken.None).Wait());

            // Assert
            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
            Assert.Same(exception, thrown);
            Assert.Same(exception, traceWriter.Traces[1].Exception);
        }
Пример #28
0
        public async Task ExecuteAsync_IfInnerResultTaskIsFaulted_ExecutesFiltersAndReturnsFaultedTaskIfNotHandled()
        {
            // Arrange
            List <string>     log                   = new List <string>();
            HttpActionContext actionContext         = ContextUtil.CreateActionContext();
            Exception         exceptionSeenByFilter = null;
            var exceptionFilter = CreateExceptionFilter(
                (ec, ct) =>
            {
                exceptionSeenByFilter = ec.Exception;
                log.Add("exceptionFilter");
                return(Task.Factory.StartNew(() => { }));
            }
                );
            var filters = new IExceptionFilter[] { exceptionFilter };
            IExceptionLogger exceptionLogger = CreateExceptionLogger(
                (c, i) =>
            {
                log.Add("exceptionLogger");
                return(Task.FromResult(0));
            }
                );
            IExceptionHandler exceptionHandler = CreateStubExceptionHandler();
            var expectedException = new Exception();
            var actionResult      = CreateStubActionResult(
                TaskHelpers.FromError <HttpResponseMessage>(expectedException)
                );

            IHttpActionResult product = CreateProductUnderTest(
                actionContext,
                filters,
                exceptionLogger,
                exceptionHandler,
                actionResult
                );

            // Act & Assert
            var exception = await Assert.ThrowsAsync <Exception>(
                () => product.ExecuteAsync(CancellationToken.None)
                );

            Assert.Same(expectedException, exception);
            Assert.Same(expectedException, exceptionSeenByFilter);
            Assert.Equal(new string[] { "exceptionLogger", "exceptionFilter" }, log.ToArray());
        }
Пример #29
0
        public async Task ExecuteAuthorizationFilterAsync_IfContinuationSucceeded_ReturnsSuccessTask()
        {
            // Arrange
            HttpActionContext context = ContextUtil.CreateActionContext();
            Mock <AuthorizationFilterAttribute> filterMock = new Mock <AuthorizationFilterAttribute>()
            {
                CallBase = true,
            };

            var filter = (IAuthorizationFilter)filterMock.Object;
            HttpResponseMessage expectedResponse = new HttpResponseMessage();

            // Act
            var response = await filter.ExecuteAuthorizationFilterAsync(context, CancellationToken.None, () => Task.FromResult(expectedResponse));

            // Assert
            Assert.Same(expectedResponse, response);
        }
        public void ExecuteActionFilterAsync_IfContinuationTaskWasCanceled_ReturnsCanceledTask()
        {
            // Arrange
            HttpActionContext            context    = ContextUtil.CreateActionContext();
            Mock <ActionFilterAttribute> filterMock = new Mock <ActionFilterAttribute>()
            {
                CallBase = true,
            };

            var filter = (IActionFilter)filterMock.Object;

            // Act
            var result = filter.ExecuteActionFilterAsync(context, CancellationToken.None, () => TaskHelpers.Canceled <HttpResponseMessage>());

            // Assert
            result.WaitUntilCompleted();
            Assert.True(result.IsCanceled);
        }