// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System; using System.Linq; using System.Web.Mvc; using Moq; using Xunit; namespace Microsoft.Web.Mvc.ModelBinding.Test { public class ComplexModelDtoModelBinderTest { [Fact] public void BindModel() { // Arrange ControllerContext controllerContext = new ControllerContext(); MyModel model = new MyModel(); ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => model, typeof(MyModel)); ComplexModelDto dto = new ComplexModelDto(modelMetadata, modelMetadata.Properties); Mock mockStringBinder = new Mock(); mockStringBinder .Setup(b => b.BindModel(controllerContext, It.IsAny())) .Returns( delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) { Assert.Equal(typeof(string), mbc.ModelType); Assert.Equal("theModel.StringProperty", mbc.ModelName); mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.StringProperty"); mbc.Model = "someStringValue"; return true; }); Mock mockIntBinder = new Mock(); mockIntBinder .Setup(b => b.BindModel(controllerContext, It.IsAny())) .Returns( delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) { Assert.Equal(typeof(int), mbc.ModelType); Assert.Equal("theModel.IntProperty", mbc.ModelName); mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.IntProperty"); mbc.Model = 42; return true; }); Mock mockDateTimeBinder = new Mock(); mockDateTimeBinder .Setup(b => b.BindModel(controllerContext, It.IsAny())) .Returns( delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) { Assert.Equal(typeof(DateTime), mbc.ModelType); Assert.Equal("theModel.DateTimeProperty", mbc.ModelName); return false; }); ModelBinderProviderCollection binders = new ModelBinderProviderCollection(); binders.RegisterBinderForType(typeof(string), mockStringBinder.Object, true /* suppressPrefixCheck */); binders.RegisterBinderForType(typeof(int), mockIntBinder.Object, true /* suppressPrefixCheck */); binders.RegisterBinderForType(typeof(DateTime), mockDateTimeBinder.Object, true /* suppressPrefixCheck */); ExtensibleModelBindingContext parentBindingContext = new ExtensibleModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => dto, typeof(ComplexModelDto)), ModelName = "theModel", ModelBinderProviders = binders }; ComplexModelDtoModelBinder binder = new ComplexModelDtoModelBinder(); // Act bool retVal = binder.BindModel(controllerContext, parentBindingContext); // Assert Assert.True(retVal); Assert.Equal(dto, parentBindingContext.Model); ComplexModelDtoResult stringDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(string)).First()]; Assert.Equal("someStringValue", stringDtoResult.Model); Assert.Equal("theModel.StringProperty", stringDtoResult.ValidationNode.ModelStateKey); ComplexModelDtoResult intDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(int)).First()]; Assert.Equal(42, intDtoResult.Model); Assert.Equal("theModel.IntProperty", intDtoResult.ValidationNode.ModelStateKey); ComplexModelDtoResult dateTimeDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(DateTime)).First()]; Assert.Null(dateTimeDtoResult); } private static ModelBindingContext GetBindingContext(Type modelType) { return new ModelBindingContext { ModelMetadata = new ModelMetadata(new Mock().Object, null, null, modelType, "SomeProperty") }; } private sealed class MyModel { public string StringProperty { get; set; } public int IntProperty { get; set; } public object ObjectProperty { get; set; } // no binding should happen since no registered binder public DateTime DateTimeProperty { get; set; } // registered binder returns false } } }