Fix #2986 - Make ModelMetadata getters null-safe

This commit is contained in:
Ryan Nowak 2015-08-19 08:37:18 -07:00
parent 8b5bb0133d
commit b5c9d905d9
3 changed files with 21 additions and 6 deletions

View File

@ -122,7 +122,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
var propertyEntry = new DefaultMetadataDetails(propertyKey, attributes); var propertyEntry = new DefaultMetadataDetails(propertyKey, attributes);
if (propertyHelper.Property.CanRead && propertyHelper.Property.GetMethod?.IsPublic == true) 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 && if (propertyHelper.Property.CanWrite &&

View File

@ -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 // 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 // because they will be overwritten if binding succeeds. Arrays are never reused because they cannot
// be resized. // be resized.
// if (propertyMetadata.PropertyGetter != null &&
// ModelMetadata.PropertyGetter is not null safe; use it only if Model is non-null.
if (bindingContext.Model != null &&
propertyMetadata.PropertyGetter != null &&
propertyMetadata.IsComplexType && propertyMetadata.IsComplexType &&
!propertyMetadata.ModelType.IsArray) !propertyMetadata.ModelType.IsArray)
{ {

View File

@ -140,6 +140,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
Assert.Equal(typeof(string), propertyMetadata.ModelType); 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() private static DefaultModelMetadataProvider CreateProvider()
{ {
return new DefaultModelMetadataProvider(new EmptyCompositeMetadataDetailsProvider()); return new DefaultModelMetadataProvider(new EmptyCompositeMetadataDetailsProvider());
@ -149,7 +166,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
private class ModelType private class ModelType
{ {
[Model("OnProperty")] [Model("OnProperty")]
public PropertyType Property1 { get; } public PropertyType Property1 { get; } = new PropertyType();
public PropertyType Property2 { get; set; } public PropertyType Property2 { get; set; }
} }