// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic; using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.Metadata.Providers; using System.Web.Http.Util; using Moq; using Xunit; namespace System.Web.Http.ModelBinding.Binders { public class KeyValuePairModelBinderTest { [Fact] public void BindModel_MissingKey_ReturnsFalse() { // Arrange KeyValuePairModelBinder binder = new KeyValuePairModelBinder(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair)), ModelName = "someName", ValueProvider = new SimpleHttpValueProvider() }; HttpActionContext context = ContextUtil.CreateActionContext(); context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(KeyValuePair), binder)); // Act bool retVal = binder.BindModel(context, bindingContext); // Assert Assert.False(retVal); Assert.Null(bindingContext.Model); Assert.Empty(bindingContext.ValidationNode.ChildNodes); } [Fact] public void BindModel_MissingValue_ReturnsTrue() { // Arrange Mock mockIntBinder = new Mock(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair)), ModelName = "someName", ValueProvider = new SimpleHttpValueProvider() }; HttpActionContext context = ContextUtil.CreateActionContext(); context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object) { SuppressPrefixCheck = true }); mockIntBinder .Setup(o => o.BindModel(context, It.IsAny())) .Returns((HttpActionContext cc, ModelBindingContext mbc) => { mbc.Model = 42; return true; }); KeyValuePairModelBinder binder = new KeyValuePairModelBinder(); // Act bool retVal = binder.BindModel(context, bindingContext); // Assert Assert.True(retVal); Assert.Null(bindingContext.Model); Assert.Equal(new[] { "someName.key" }, bindingContext.ValidationNode.ChildNodes.Select(n => n.ModelStateKey).ToArray()); } [Fact] public void BindModel_SubBindingSucceeds() { // Arrange Mock mockIntBinder = new Mock(); Mock mockStringBinder = new Mock(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair)), ModelName = "someName", ValueProvider = new SimpleHttpValueProvider() }; HttpActionContext context = ContextUtil.CreateActionContext(); context.ControllerContext.Configuration.Services.ReplaceRange(typeof(ModelBinderProvider), new 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())) .Returns((HttpActionContext cc, ModelBindingContext mbc) => { mbc.Model = 42; return true; }); mockStringBinder .Setup(o => o.BindModel(context, It.IsAny())) .Returns((HttpActionContext cc, ModelBindingContext mbc) => { mbc.Model = "forty-two"; return true; }); KeyValuePairModelBinder binder = new KeyValuePairModelBinder(); // Act bool retVal = binder.BindModel(context, bindingContext); // Assert Assert.True(retVal); Assert.Equal(new KeyValuePair(42, "forty-two"), bindingContext.Model); Assert.Equal(new[] { "someName.key", "someName.value" }, bindingContext.ValidationNode.ChildNodes.Select(n => n.ModelStateKey).ToArray()); } } }