Fix #2986 - Make ModelMetadata getters null-safe
This commit is contained in:
parent
8b5bb0133d
commit
b5c9d905d9
|
|
@ -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 &&
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue