diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadataProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadataProvider.cs index 2ec19ee739..334d3bc10d 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadataProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadataProvider.cs @@ -122,7 +122,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata var propertyEntry = new DefaultMetadataDetails(propertyKey, attributes); if (propertyHelper.Property.CanRead && propertyHelper.Property.GetMethod?.IsPublic == true) { - propertyEntry.PropertyGetter = propertyHelper.ValueGetter; + var getter = PropertyHelper.MakeNullSafeFastPropertyGetter(propertyHelper.Property); + propertyEntry.PropertyGetter = getter; } if (propertyHelper.Property.CanWrite && diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs index 8561264aa5..fda668a1f5 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs @@ -287,10 +287,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // instances or overwrite inner properties that are not bound. No need for this with simple values // because they will be overwritten if binding succeeds. Arrays are never reused because they cannot // be resized. - // - // ModelMetadata.PropertyGetter is not null safe; use it only if Model is non-null. - if (bindingContext.Model != null && - propertyMetadata.PropertyGetter != null && + if (propertyMetadata.PropertyGetter != null && propertyMetadata.IsComplexType && !propertyMetadata.ModelType.IsArray) { diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/DefaultModelMetadataProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/DefaultModelMetadataProviderTest.cs index f1984e68e1..b29a09102c 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/DefaultModelMetadataProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/Metadata/DefaultModelMetadataProviderTest.cs @@ -140,6 +140,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata Assert.Equal(typeof(string), propertyMetadata.ModelType); } + [Fact] + public void GetMetadataForProperties_PropertyGetter_IsNullSafe() + { + // Arrange + var provider = CreateProvider(); + + // Act + var metadata = provider.GetMetadataForProperties(typeof(ModelType)); + + // Assert + foreach (var property in metadata) + { + Assert.NotNull(property.PropertyGetter); + Assert.Null(property.PropertyGetter(null)); + } + } + private static DefaultModelMetadataProvider CreateProvider() { return new DefaultModelMetadataProvider(new EmptyCompositeMetadataDetailsProvider()); @@ -149,7 +166,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata private class ModelType { [Model("OnProperty")] - public PropertyType Property1 { get; } + public PropertyType Property1 { get; } = new PropertyType(); public PropertyType Property2 { get; set; } }