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