diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsMetadataAttributes.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsMetadataAttributes.cs index 03b1779f28..67e18709fd 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsMetadataAttributes.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsMetadataAttributes.cs @@ -37,8 +37,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding } /// - /// Gets (or sets in subclasses) found in collection passed - /// to the constructor, if any. + /// Gets (or sets in subclasses) found in collection + /// passed to the constructor, + /// if any. /// public IEnumerable BinderTypeProviders { get; set; } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs index e4148cd399..ed0a28608d 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Metadata/CachedDataAnnotationsModelMetadata.cs @@ -39,9 +39,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { if (PrototypeCache.BinderTypeProviders != null) { - // The need for fallback here is to handle cases where a model binder is specified - // on a type and on a parameter to an action. - // // We want to respect the value set by the parameter (if any), and use the value specifed // on the type as a fallback. // diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/ModelBindingTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/ModelBindingTests.cs index de7c18dd4f..a414aca54d 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/ModelBindingTests.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/ModelBindingTests.cs @@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests // Act var response = await client.PostAsync("http://localhost/Home/GetCustomer?Id=1234", content); - + // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var customer = JsonConvert.DeserializeObject( diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/CachedDataAnnotationsMetadataAttributesTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/CachedDataAnnotationsMetadataAttributesTest.cs index 0775379dc1..6671c1fe64 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/CachedDataAnnotationsMetadataAttributesTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/CachedDataAnnotationsMetadataAttributesTest.cs @@ -86,12 +86,31 @@ namespace Microsoft.AspNet.Mvc.ModelBinding var result = cache.PropertyBindingInfo.ToArray(); // Assert + Assert.Equal(propertyBindingInfos.Length, result.Length); for (var index = 0; index < propertyBindingInfos.Length; index++) { Assert.Same(propertyBindingInfos[index], result[index]); } } + [Fact] + public void Constructor_FindsBinderTypeProviders() + { + // Arrange + var providers = new[] { new TestBinderTypeProvider(), new TestBinderTypeProvider() }; + + // Act + var cache = new CachedDataAnnotationsMetadataAttributes(providers); + var result = cache.BinderTypeProviders.ToArray(); + + // Assert + Assert.Equal(providers.Length, result.Length); + for (var index = 0; index < providers.Length; index++) + { + Assert.Same(providers[index], result[index]); + } + } + [Fact] public void Constructor_FindsDisplayFormat_FromDataType() { @@ -123,5 +142,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // Assert Assert.Same(displayFormat, result); } + + private class TestBinderTypeProvider : IBinderTypeProviderMetadata + { + public Type BinderType { get; set; } + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/CachedDataAnnotationsModelMetadataTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/CachedDataAnnotationsModelMetadataTest.cs index d90fc065c6..c48ef4936f 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/CachedDataAnnotationsModelMetadataTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/CachedDataAnnotationsModelMetadataTest.cs @@ -52,6 +52,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding Assert.Null(metadata.BinderModelName); Assert.Null(metadata.BinderMetadata); + Assert.Null(metadata.BinderType); Assert.Empty(metadata.BinderIncludeProperties); Assert.Null(metadata.BinderExcludeProperties); } @@ -399,6 +400,79 @@ namespace Microsoft.AspNet.Mvc.ModelBinding Assert.Null(metadata.EditFormatString); } + [Fact] + public void Constructor_FindsBinderTypeProviders_Null() + { + // Arrange + var provider = new DataAnnotationsModelMetadataProvider(); + + var binderProviders = new[] { new TestBinderTypeProvider(), new TestBinderTypeProvider() }; + + // Act + var metadata = new CachedDataAnnotationsModelMetadata( + provider, + containerType: null, + modelType: typeof(object), + propertyName: null, + attributes: binderProviders); + + // Assert + Assert.Null(metadata.BinderType); + } + + [Fact] + public void Constructor_FindsBinderTypeProviders_Fallback() + { + // Arrange + var provider = new DataAnnotationsModelMetadataProvider(); + + var binderProviders = new[] + { + new TestBinderTypeProvider(), + new TestBinderTypeProvider() { BinderType = typeof(string) } + }; + + // Act + var metadata = new CachedDataAnnotationsModelMetadata( + provider, + containerType: null, + modelType: typeof(object), + propertyName: null, + attributes: binderProviders); + + // Assert + Assert.Same(typeof(string), metadata.BinderType); + } + + [Fact] + public void Constructor_FindsBinderTypeProviders_FirstAttributeHasPrecedence() + { + // Arrange + var provider = new DataAnnotationsModelMetadataProvider(); + + var binderProviders = new[] + { + new TestBinderTypeProvider() { BinderType = typeof(int) }, + new TestBinderTypeProvider() { BinderType = typeof(string) } + }; + + // Act + var metadata = new CachedDataAnnotationsModelMetadata( + provider, + containerType: null, + modelType: typeof(object), + propertyName: null, + attributes: binderProviders); + + // Assert + Assert.Same(typeof(int), metadata.BinderType); + } + + private class TestBinderTypeProvider : IBinderTypeProviderMetadata + { + public Type BinderType { get; set; } + } + private class DataTypeWithCustomDisplayFormat : DataTypeAttribute { public DataTypeWithCustomDisplayFormat() : base("Custom datatype") diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs index 6fc4f7c1a0..78a5ac233d 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Metadata/ModelMetadataTest.cs @@ -54,6 +54,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { m => m.BinderModelName = null, m => m.BinderModelName, null }, { m => m.BinderModelName = "newModelName", m => m.BinderModelName, "newModelName" }, { m => m.BinderModelName = string.Empty, m => m.BinderModelName, string.Empty }, + { m => m.BinderType = null, m => m.BinderType, null }, + { m => m.BinderType = typeof(string), m => m.BinderType, typeof(string) }, { m => m.BinderIncludeProperties = null, m => m.BinderIncludeProperties, null }, { m => m.BinderIncludeProperties = emptyPropertyList, @@ -124,6 +126,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding Assert.Equal(ModelMetadata.DefaultOrder, metadata.Order); Assert.Null(metadata.BinderModelName); + Assert.Null(metadata.BinderType); Assert.Null(metadata.BinderMetadata); Assert.Null(metadata.BinderIncludeProperties); Assert.Null(metadata.BinderExcludeProperties);