Use the declared type to infer NullableContextOptions (#15134)
* Use the declared type to infer NullableContextOptions Prior to this change MVC used the runtime type rather than the declared type to determine the nullability of a property based on state. In the case of inheritance, this can be erroneous since the declared type may have a different nullability context than the model type. This change addresses this by adding content to `ModelIdentity` that allows inspecting the declared type. * Add an overload to `ModelMetadataIdentity` that allows flowing `PropertyInfo` * Use the declared type in `DataAnnotationsMetadataProvider` to determine nullability based on context. Fixes https://github.com/aspnet/AspNetCore/issues/14812
This commit is contained in:
parent
0de5791427
commit
cdae83efae
|
|
@ -883,10 +883,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
public System.Type ModelType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public System.Reflection.ParameterInfo ParameterInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public System.Reflection.PropertyInfo PropertyInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public bool Equals(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity other) { throw null; }
|
||||
public override bool Equals(object obj) { throw null; }
|
||||
public static Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity ForParameter(System.Reflection.ParameterInfo parameter) { throw null; }
|
||||
public static Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity ForParameter(System.Reflection.ParameterInfo parameter, System.Type modelType) { throw null; }
|
||||
public static Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity ForProperty(System.Reflection.PropertyInfo propertyInfo, System.Type modelType, System.Type containerType) { throw null; }
|
||||
[System.ObsoleteAttribute("This API is obsolete and may be removed in a future release.")]
|
||||
public static Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity ForProperty(System.Type modelType, string name, System.Type containerType) { throw null; }
|
||||
public static Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity ForType(System.Type modelType) { throw null; }
|
||||
public override int GetHashCode() { throw null; }
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
Type modelType,
|
||||
string name = null,
|
||||
Type containerType = null,
|
||||
ParameterInfo parameterInfo = null)
|
||||
ParameterInfo parameterInfo = null,
|
||||
PropertyInfo propertyInfo = null)
|
||||
{
|
||||
ModelType = modelType;
|
||||
Name = name;
|
||||
ContainerType = containerType;
|
||||
ParameterInfo = parameterInfo;
|
||||
PropertyInfo = propertyInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -47,6 +49,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
/// <param name="name">The name of the property.</param>
|
||||
/// <param name="containerType">The container type of the model property.</param>
|
||||
/// <returns>A <see cref="ModelMetadataIdentity"/>.</returns>
|
||||
[Obsolete("This API is obsolete and may be removed in a future release.")]
|
||||
public static ModelMetadataIdentity ForProperty(
|
||||
Type modelType,
|
||||
string name,
|
||||
|
|
@ -70,6 +73,36 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
return new ModelMetadataIdentity(modelType, name, containerType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ModelMetadataIdentity"/> for the provided property.
|
||||
/// </summary>
|
||||
/// <param name="modelType">The model type.</param>
|
||||
/// <param name="propertyInfo">The property.</param>
|
||||
/// <param name="containerType">The container type of the model property.</param>
|
||||
/// <returns>A <see cref="ModelMetadataIdentity"/>.</returns>
|
||||
public static ModelMetadataIdentity ForProperty(
|
||||
PropertyInfo propertyInfo,
|
||||
Type modelType,
|
||||
Type containerType)
|
||||
{
|
||||
if (propertyInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyInfo));
|
||||
}
|
||||
|
||||
if (modelType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
if (containerType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(containerType));
|
||||
}
|
||||
|
||||
return new ModelMetadataIdentity(modelType, propertyInfo.Name, containerType, propertyInfo: propertyInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ModelMetadataIdentity"/> for the provided parameter.
|
||||
/// </summary>
|
||||
|
|
@ -145,6 +178,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
/// </summary>
|
||||
public ParameterInfo ParameterInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a descriptor for the property, or <c>null</c> if this instance
|
||||
/// does not represent a property.
|
||||
/// </summary>
|
||||
public PropertyInfo PropertyInfo { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(ModelMetadataIdentity other)
|
||||
{
|
||||
|
|
@ -152,7 +191,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
ContainerType == other.ContainerType &&
|
||||
ModelType == other.ModelType &&
|
||||
Name == other.Name &&
|
||||
ParameterInfo == other.ParameterInfo;
|
||||
ParameterInfo == other.ParameterInfo &&
|
||||
PropertyInfo == other.PropertyInfo;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -170,6 +210,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
hash.Add(ModelType);
|
||||
hash.Add(Name, StringComparer.Ordinal);
|
||||
hash.Add(ParameterInfo);
|
||||
hash.Add(PropertyInfo);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,7 +270,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
public void ContainerType_ReturnExpectedMetadata_ForProperty()
|
||||
{
|
||||
// Arrange & Act
|
||||
var metadata = new TestModelMetadata(typeof(int), nameof(string.Length), typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var metadata = new TestModelMetadata(property, typeof(int), typeof(string));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(typeof(string), metadata.ContainerType);
|
||||
|
|
@ -308,7 +309,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
public void Names_ReturnExpectedMetadata_ForProperty()
|
||||
{
|
||||
// Arrange & Act
|
||||
var metadata = new TestModelMetadata(typeof(int), nameof(string.Length), typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var metadata = new TestModelMetadata(property, typeof(int), typeof(string));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(nameof(string.Length), metadata.Name);
|
||||
|
|
@ -322,7 +324,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
public void GetDisplayName_ReturnsDisplayName_IfSet()
|
||||
{
|
||||
// Arrange
|
||||
var metadata = new TestModelMetadata(typeof(int), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var metadata = new TestModelMetadata(property, typeof(int), typeof(string));
|
||||
metadata.SetDisplayName("displayName");
|
||||
|
||||
// Act
|
||||
|
|
@ -351,7 +354,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
public void GetDisplayName_ReturnsPropertyName_WhenSetAndDisplayNameIsNull()
|
||||
{
|
||||
// Arrange
|
||||
var metadata = new TestModelMetadata(typeof(int), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var metadata = new TestModelMetadata(property, typeof(int), typeof(string));
|
||||
|
||||
// Act
|
||||
var result = metadata.GetDisplayName();
|
||||
|
|
@ -419,8 +423,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{
|
||||
}
|
||||
|
||||
public TestModelMetadata(Type modelType, string propertyName, Type containerType)
|
||||
: base(ModelMetadataIdentity.ForProperty(modelType, propertyName, containerType))
|
||||
public TestModelMetadata(PropertyInfo propertyInfo, Type modelType, Type containerType)
|
||||
: base(ModelMetadataIdentity.ForProperty(propertyInfo, modelType, containerType))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
private ModelMetadataCacheEntry GetCacheEntry(PropertyInfo property, Type modelType)
|
||||
{
|
||||
return _typeCache.GetOrAdd(
|
||||
ModelMetadataIdentity.ForProperty(modelType, property.Name, property.DeclaringType),
|
||||
ModelMetadataIdentity.ForProperty(property, modelType, property.DeclaringType),
|
||||
_cacheEntryFactory);
|
||||
}
|
||||
|
||||
|
|
@ -275,8 +275,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var propertyHelper = propertyHelpers[i];
|
||||
|
||||
var propertyKey = ModelMetadataIdentity.ForProperty(
|
||||
propertyHelper.Property,
|
||||
propertyHelper.Property.PropertyType,
|
||||
propertyHelper.Name,
|
||||
key.ModelType);
|
||||
|
||||
var propertyEntry = CreateSinglePropertyDetails(propertyKey, propertyHelper);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -27,7 +25,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
|
||||
var context = new DefaultModelBindingContext();
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var identity = ModelMetadataIdentity.ForProperty(typeof(int), property, typeof(string));
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
context.ModelMetadata = new Mock<ModelMetadata>(identity).Object;
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -184,7 +184,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -207,7 +207,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -230,7 +230,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -253,7 +253,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -420,7 +420,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -438,7 +438,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
{
|
||||
// Arrange
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindRequiredOnClass)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(BindRequiredOnClass).GetProperty(nameof(BindRequiredOnClass.Property)), typeof(int), typeof(BindRequiredOnClass)),
|
||||
new ModelAttributes(new object[0], new object[0], null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -456,7 +456,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
{
|
||||
// Arrange
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindNeverOnClass)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(BindNeverOnClass).GetProperty(nameof(BindNeverOnClass.Property)), typeof(int), typeof(BindNeverOnClass)),
|
||||
new ModelAttributes(new object[0], new object[0], null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -474,7 +474,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
{
|
||||
// Arrange
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(InheritedBindNeverOnClass)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(BindNeverOnClass).GetProperty(nameof(BindNeverOnClass.Property)), typeof(int), typeof(BindNeverOnClass)),
|
||||
new ModelAttributes(new object[0], new object[0], null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -497,7 +497,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindNeverOnClass)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(BindNeverOnClass).GetProperty(nameof(BindNeverOnClass.Property)), typeof(int), typeof(BindNeverOnClass)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -520,7 +520,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindNeverOnClass)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(BindNeverOnClass).GetProperty(nameof(BindNeverOnClass.Property)), typeof(int), typeof(BindNeverOnClass)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -543,7 +543,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(InheritedBindNeverOnClass)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(InheritedBindNeverOnClass).GetProperty(nameof(InheritedBindNeverOnClass.Property)), typeof(int), typeof(InheritedBindNeverOnClass)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -566,7 +566,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindRequiredOnClass)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(BindRequiredOnClass).GetProperty(nameof(BindRequiredOnClass.Property)), typeof(int), typeof(BindRequiredOnClass)),
|
||||
new ModelAttributes(new object[0], propertyAttributes, null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -585,7 +585,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
{
|
||||
// Arrange
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(string), "Property", typeof(BindRequiredOverridesInheritedBindNever)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(BindRequiredOverridesInheritedBindNever).GetProperty(nameof(BindRequiredOverridesInheritedBindNever.Property)), typeof(int), typeof(BindRequiredOverridesInheritedBindNever)),
|
||||
new ModelAttributes(new object[0], new object[0], null));
|
||||
|
||||
var provider = new DefaultBindingMetadataProvider();
|
||||
|
|
@ -641,7 +641,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
};
|
||||
|
||||
var context = new BindingMetadataProviderContext(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
|
||||
new ModelAttributes(typeAttributes, new object[0], null));
|
||||
|
||||
// These values shouldn't be changed since this is a Type-Metadata
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var provider = new EmptyModelMetadataProvider();
|
||||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(string), "Message", typeof(Exception));
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(Exception).GetProperty(nameof(Exception.Message)), typeof(string), typeof(Exception));
|
||||
var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0], new object[0], null));
|
||||
|
||||
// Act
|
||||
|
|
@ -123,8 +123,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(TypeWithProperties).GetProperty(nameof(TypeWithProperties.PublicGetPublicSetProperty)),
|
||||
typeof(string),
|
||||
nameof(TypeWithProperties.PublicGetPublicSetProperty),
|
||||
typeof(TypeWithProperties));
|
||||
|
||||
var attributes = new ModelAttributes(Array.Empty<object>(), Array.Empty<object>(), null);
|
||||
|
|
@ -160,8 +160,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(TypeWithProperties).GetProperty(nameof(TypeWithProperties.PublicGetPublicSetProperty)),
|
||||
typeof(string),
|
||||
nameof(TypeWithProperties.PublicGetPublicSetProperty),
|
||||
typeof(TypeWithProperties));
|
||||
|
||||
var attributes = new ModelAttributes(Array.Empty<object>(), Array.Empty<object>(), null);
|
||||
|
|
@ -197,8 +197,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(TypeWithProperties).GetProperty(nameof(TypeWithProperties.PublicGetPublicSetProperty)),
|
||||
typeof(string),
|
||||
nameof(TypeWithProperties.PublicGetPublicSetProperty),
|
||||
typeof(TypeWithProperties));
|
||||
|
||||
var attributes = new ModelAttributes(Array.Empty<object>(), Array.Empty<object>(), null);
|
||||
|
|
@ -393,19 +393,22 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var provider = new Mock<IModelMetadataProvider>(MockBehavior.Strict);
|
||||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
|
||||
var prop1 = typeof(Exception).GetProperty(nameof(Exception.Message));
|
||||
var prop2 = typeof(Exception).GetProperty(nameof(Exception.StackTrace));
|
||||
|
||||
var expectedProperties = new DefaultModelMetadata[]
|
||||
{
|
||||
new DefaultModelMetadata(
|
||||
provider.Object,
|
||||
detailsProvider,
|
||||
new DefaultMetadataDetails(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Prop1", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(prop1, typeof(int), typeof(string)),
|
||||
attributes: new ModelAttributes(new object[0], new object[0], null))),
|
||||
new DefaultModelMetadata(
|
||||
provider.Object,
|
||||
detailsProvider,
|
||||
new DefaultMetadataDetails(
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), "Prop2", typeof(string)),
|
||||
ModelMetadataIdentity.ForProperty(prop2, typeof(int), typeof(string)),
|
||||
attributes: new ModelAttributes(new object[0], new object[0], null))),
|
||||
};
|
||||
|
||||
|
|
@ -475,7 +478,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
provider.Object,
|
||||
detailsProvider,
|
||||
new DefaultMetadataDetails(
|
||||
#pragma warning disable CS0618 // Using the obsolete overload does not affect the intent of this test, but fixing it requires a lot of code churn.
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), originalName, typeof(string)),
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
attributes: new ModelAttributes(new object[0], new object[0], null))));
|
||||
}
|
||||
|
||||
|
|
@ -575,7 +580,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
foreach (var kvp in originalNamesAndOrders)
|
||||
{
|
||||
var propertyCache = new DefaultMetadataDetails(
|
||||
#pragma warning disable CS0618 // Using the obsolete overload does not affect the intent of this test, but fixing it requires a lot of code churn.
|
||||
ModelMetadataIdentity.ForProperty(typeof(int), kvp.Key, typeof(string)),
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
attributes: new ModelAttributes(new object[0], new object[0], null))
|
||||
{
|
||||
DisplayMetadata = new DisplayMetadata(),
|
||||
|
|
@ -934,7 +941,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
// Arrange
|
||||
var property = GetType()
|
||||
.GetProperty(nameof(CalculateHasValidators_PropertyMetadata_TypeHasNoValidatorsProperty), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
var modelIdentity = ModelMetadataIdentity.ForProperty(property.PropertyType, property.Name, GetType());
|
||||
var modelIdentity = ModelMetadataIdentity.ForProperty(property, property.PropertyType, GetType());
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, Mock.Of<IModelMetadataProvider>(), false);
|
||||
|
||||
// Act
|
||||
|
|
@ -997,7 +1004,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
|
||||
var propertyIdentity = ModelMetadataIdentity.ForProperty(typeof(int), nameof(TypeWithProperties.PublicGetPublicSetProperty), typeof(string));
|
||||
var property = typeof(TypeWithProperties).GetProperty(nameof(TypeWithProperties.PublicGetPublicSetProperty));
|
||||
var propertyIdentity = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(TypeWithProperties));
|
||||
var propertyMetadata = new Mock<ModelMetadata>(propertyIdentity);
|
||||
|
||||
metadataProvider
|
||||
|
|
@ -1021,10 +1029,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
|
||||
var property1Identity = ModelMetadataIdentity.ForProperty(typeof(int), nameof(TypeWithProperties.PublicGetPublicSetProperty), typeof(string));
|
||||
var property1Identity = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(TypeWithProperties.PublicGetPublicSetProperty)), typeof(int), modelType);
|
||||
var property1Metadata = CreateModelMetadata(property1Identity, metadataProvider.Object, false);
|
||||
|
||||
var property2Identity = ModelMetadataIdentity.ForProperty(typeof(int), nameof(TypeWithProperties.PublicGetProtectedSetProperty), typeof(string));
|
||||
var property2Identity = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(TypeWithProperties.PublicGetProtectedSetProperty)), typeof(int), modelType);
|
||||
var property2Metadata = CreateModelMetadata(property2Identity, metadataProvider.Object, true);
|
||||
|
||||
metadataProvider
|
||||
|
|
@ -1048,7 +1056,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
|
||||
var propertyIdentity = ModelMetadataIdentity.ForProperty(typeof(int), nameof(TypeWithProperties.PublicGetPublicSetProperty), typeof(string));
|
||||
var propertyIdentity = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(TypeWithProperties.PublicGetPublicSetProperty)), typeof(int), modelType);
|
||||
var propertyMetadata = CreateModelMetadata(propertyIdentity, metadataProvider.Object, null);
|
||||
|
||||
metadataProvider
|
||||
|
|
@ -1072,10 +1080,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
|
||||
var property1Identity = ModelMetadataIdentity.ForProperty(typeof(int), nameof(TypeWithProperties.PublicGetPublicSetProperty), modelType);
|
||||
var property1Identity = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(TypeWithProperties.PublicGetPublicSetProperty)), typeof(int), modelType);
|
||||
var property1Metadata = CreateModelMetadata(property1Identity, metadataProvider.Object, false);
|
||||
|
||||
var property2Identity = ModelMetadataIdentity.ForProperty(typeof(int), nameof(TypeWithProperties.PublicGetProtectedSetProperty), modelType);
|
||||
var property2Identity = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(TypeWithProperties.PublicGetProtectedSetProperty)), typeof(int), modelType);
|
||||
var property2Metadata = CreateModelMetadata(property2Identity, metadataProvider.Object, false);
|
||||
|
||||
metadataProvider
|
||||
|
|
@ -1099,18 +1107,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
|
||||
var employeeId = ModelMetadataIdentity.ForProperty(typeof(int), nameof(Employee.Id), modelType);
|
||||
var employeeId = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Id)), typeof(int), modelType);
|
||||
var employeeIdMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
var employeeUnit = ModelMetadataIdentity.ForProperty(typeof(BusinessUnit), nameof(Employee.Unit), modelType);
|
||||
var employeeUnit = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Unit)), typeof(BusinessUnit), modelType);
|
||||
var employeeUnitMetadata = CreateModelMetadata(employeeUnit, metadataProvider.Object, false);
|
||||
var employeeManager = ModelMetadataIdentity.ForProperty(typeof(Employee), nameof(Employee.Unit), modelType);
|
||||
var employeeManager = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Manager)), typeof(Employee), modelType);
|
||||
var employeeManagerMetadata = CreateModelMetadata(employeeManager, metadataProvider.Object, false);
|
||||
var employeeEmployees = ModelMetadataIdentity.ForProperty(typeof(List<Employee>), nameof(Employee.Employees), modelType);
|
||||
var employeeEmployees = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Employees)), typeof(List<Employee>), modelType);
|
||||
var employeeEmployeesMetadata = CreateModelMetadata(employeeEmployees, metadataProvider.Object, false);
|
||||
|
||||
var unitHead = ModelMetadataIdentity.ForProperty(typeof(Employee), nameof(BusinessUnit.Head), modelType);
|
||||
var unitModel = typeof(BusinessUnit);
|
||||
var unitHead = ModelMetadataIdentity.ForProperty(unitModel.GetProperty(nameof(BusinessUnit.Head)), typeof(Employee), unitModel);
|
||||
var unitHeadMetadata = CreateModelMetadata(unitHead, metadataProvider.Object, false);
|
||||
var unitId = ModelMetadataIdentity.ForProperty(typeof(int), nameof(BusinessUnit.Id), modelType);
|
||||
var unitId = ModelMetadataIdentity.ForProperty(unitModel.GetProperty(nameof(BusinessUnit.Id)), typeof(int), unitModel);
|
||||
var unitIdMetadata = CreateModelMetadata(unitId, metadataProvider.Object, true); // BusinessUnit.Id has validators.
|
||||
|
||||
metadataProvider
|
||||
|
|
@ -1139,18 +1148,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
|
||||
var employeeId = ModelMetadataIdentity.ForProperty(typeof(int), nameof(Employee.Id), modelType);
|
||||
var employeeId = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Id)), typeof(int), modelType);
|
||||
var employeeIdMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
var employeeUnit = ModelMetadataIdentity.ForProperty(typeof(BusinessUnit), nameof(Employee.Unit), modelType);
|
||||
var employeeUnit = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Unit)), typeof(BusinessUnit), modelType);
|
||||
var employeeUnitMetadata = CreateModelMetadata(employeeUnit, metadataProvider.Object, false);
|
||||
var employeeManager = ModelMetadataIdentity.ForProperty(typeof(Employee), nameof(Employee.Unit), modelType);
|
||||
var employeeManager = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Manager)), typeof(Employee), modelType);
|
||||
var employeeManagerMetadata = CreateModelMetadata(employeeManager, metadataProvider.Object, false);
|
||||
var employeeEmployees = ModelMetadataIdentity.ForProperty(typeof(List<Employee>), nameof(Employee.Employees), modelType);
|
||||
var employeeEmployees = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Employees)), typeof(List<Employee>), modelType);
|
||||
var employeeEmployeesMetadata = CreateModelMetadata(employeeEmployees, metadataProvider.Object, false);
|
||||
|
||||
var unitHead = ModelMetadataIdentity.ForProperty(typeof(Employee), nameof(BusinessUnit.Head), modelType);
|
||||
var unitModel = typeof(BusinessUnit);
|
||||
var unitHead = ModelMetadataIdentity.ForProperty(unitModel.GetProperty(nameof(BusinessUnit.Head)), typeof(Employee), unitModel);
|
||||
var unitHeadMetadata = CreateModelMetadata(unitHead, metadataProvider.Object, true); // BusinessUnit.Head has validators
|
||||
var unitId = ModelMetadataIdentity.ForProperty(typeof(int), nameof(BusinessUnit.Id), modelType);
|
||||
var unitId = ModelMetadataIdentity.ForProperty(unitModel.GetProperty(nameof(BusinessUnit.Id)), typeof(int), unitModel);
|
||||
var unitIdMetadata = CreateModelMetadata(unitId, metadataProvider.Object, false);
|
||||
|
||||
metadataProvider
|
||||
|
|
@ -1181,9 +1191,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
|
||||
var employeeId = ModelMetadataIdentity.ForProperty(typeof(int), nameof(Employee.Id), modelType);
|
||||
var employeeId = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Id)), typeof(int), modelType);
|
||||
var employeeIdMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
var employeeEmployees = ModelMetadataIdentity.ForProperty(typeof(List<Employee>), nameof(Employee.Employees), modelType);
|
||||
var employeeEmployees = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Employees)), typeof(List<Employee>), modelType);
|
||||
var employeeEmployeesMetadata = CreateModelMetadata(employeeEmployees, metadataProvider.Object, false);
|
||||
|
||||
metadataProvider
|
||||
|
|
@ -1210,18 +1220,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
var modelMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
|
||||
var employeeId = ModelMetadataIdentity.ForProperty(typeof(int), nameof(Employee.Id), modelType);
|
||||
var employeeId = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Id)), typeof(int), modelType);
|
||||
var employeeIdMetadata = CreateModelMetadata(modelIdentity, metadataProvider.Object, false);
|
||||
var employeeUnit = ModelMetadataIdentity.ForProperty(typeof(BusinessUnit), nameof(Employee.Unit), modelType);
|
||||
var employeeUnit = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Unit)), typeof(BusinessUnit), modelType);
|
||||
var employeeUnitMetadata = CreateModelMetadata(employeeUnit, metadataProvider.Object, false);
|
||||
var employeeManager = ModelMetadataIdentity.ForProperty(typeof(Employee), nameof(Employee.Unit), modelType);
|
||||
var employeeManager = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Manager)), typeof(Employee), modelType);
|
||||
var employeeManagerMetadata = CreateModelMetadata(employeeManager, metadataProvider.Object, false);
|
||||
var employeeEmployeesId = ModelMetadataIdentity.ForProperty(typeof(List<Employee>), nameof(Employee.Employees), modelType);
|
||||
var employeeEmployeesId = ModelMetadataIdentity.ForProperty(modelType.GetProperty(nameof(Employee.Employees)), typeof(List<Employee>), modelType);
|
||||
var employeeEmployeesIdMetadata = CreateModelMetadata(employeeEmployeesId, metadataProvider.Object, false);
|
||||
|
||||
var unitHead = ModelMetadataIdentity.ForProperty(typeof(Employee), nameof(BusinessUnit.Head), modelType);
|
||||
var unitModel = typeof(BusinessUnit);
|
||||
var unitHead = ModelMetadataIdentity.ForProperty(unitModel.GetProperty(nameof(BusinessUnit.Head)), typeof(Employee), unitModel);
|
||||
var unitHeadMetadata = CreateModelMetadata(unitHead, metadataProvider.Object, false);
|
||||
var unitId = ModelMetadataIdentity.ForProperty(typeof(int), nameof(BusinessUnit.Id), modelType);
|
||||
var unitId = ModelMetadataIdentity.ForProperty(unitModel.GetProperty(nameof(BusinessUnit.Id)), typeof(int), unitModel);
|
||||
var unitIdMetadata = CreateModelMetadata(unitId, metadataProvider.Object, false);
|
||||
|
||||
metadataProvider
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var provider = new DefaultValidationMetadataProvider();
|
||||
|
||||
var attributes = new Attribute[] { new ValidateNeverAttribute() };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], attributes, null));
|
||||
|
||||
// Act
|
||||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var provider = new DefaultValidationMetadataProvider();
|
||||
|
||||
var attributes = new Attribute[] { new ValidateNeverAttribute() };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, new ModelAttributes(attributes, new object[0], null));
|
||||
|
||||
// Act
|
||||
|
|
@ -71,8 +71,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var provider = new DefaultValidationMetadataProvider();
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(ValidateNeverClass).GetProperty(nameof(ValidateNeverClass.ClassName)),
|
||||
typeof(string),
|
||||
nameof(ValidateNeverClass.ClassName),
|
||||
typeof(ValidateNeverClass));
|
||||
var context = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], new object[0], null));
|
||||
|
||||
|
|
@ -93,8 +93,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var provider = new DefaultValidationMetadataProvider();
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(ValidateNeverSubclass).GetProperty(nameof(ValidateNeverSubclass.SubclassName)),
|
||||
typeof(string),
|
||||
nameof(ValidateNeverSubclass.SubclassName),
|
||||
typeof(ValidateNeverSubclass));
|
||||
var context = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], new object[0], null));
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
|
||||
var attribute = new TestClientModelValidationAttribute();
|
||||
var attributes = new Attribute[] { attribute };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], attributes, null));
|
||||
|
||||
// Act
|
||||
|
|
@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
|
||||
var attribute = new TestModelValidationAttribute();
|
||||
var attributes = new Attribute[] { attribute };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], attributes, null));
|
||||
|
||||
// Act
|
||||
|
|
@ -154,7 +154,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
|
||||
var attribute = new TestValidationAttribute();
|
||||
var attributes = new Attribute[] { attribute };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, new ModelAttributes(new object[0], attributes, null));
|
||||
context.ValidationMetadata.ValidatorMetadata.Add(attribute);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var provider = new ExcludeBindingMetadataProvider(typeof(string));
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(Person).GetProperty(nameof(Person.Age)),
|
||||
typeof(int),
|
||||
nameof(Person.Age),
|
||||
typeof(Person));
|
||||
|
||||
var context = new BindingMetadataProviderContext(key, new ModelAttributes(new object[0], new object[0], null));
|
||||
|
|
@ -40,8 +40,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
var provider = new ExcludeBindingMetadataProvider(typeof(int));
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(Person).GetProperty(nameof(Person.Age)),
|
||||
typeof(int),
|
||||
nameof(Person.Age),
|
||||
typeof(Person));
|
||||
|
||||
var context = new BindingMetadataProviderContext(key, new ModelAttributes(new object[0], new object[0], null));
|
||||
|
|
|
|||
|
|
@ -366,10 +366,27 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
}
|
||||
else if (context.Key.MetadataKind == ModelMetadataKind.Property)
|
||||
{
|
||||
addInferredRequiredAttribute = IsNullableReferenceType(
|
||||
context.Key.ContainerType,
|
||||
member: null,
|
||||
context.PropertyAttributes);
|
||||
var property = context.Key.PropertyInfo;
|
||||
if (property is null)
|
||||
{
|
||||
// PropertyInfo was unavailable on ModelIdentity prior to 3.1.
|
||||
// Making a cogent argument about the nullability of the property requires inspecting the declared type,
|
||||
// since looking at the runtime type may result in false positives: https://github.com/aspnet/AspNetCore/issues/14812
|
||||
// The only way we could arrive here is if the ModelMetadata was constructed using the non-default provider.
|
||||
// We'll cursorily examine the attributes on the property, but not the ContainerType to make a decision about it's nullability.
|
||||
|
||||
if (HasNullableAttribute(context.PropertyAttributes, out var propertyHasNullableAttribute))
|
||||
{
|
||||
addInferredRequiredAttribute = propertyHasNullableAttribute;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addInferredRequiredAttribute = IsNullableReferenceType(
|
||||
property.DeclaringType,
|
||||
member: null,
|
||||
context.PropertyAttributes);
|
||||
}
|
||||
}
|
||||
else if (context.Key.MetadataKind == ModelMetadataKind.Parameter)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -599,13 +599,13 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
provider.CreateDisplayMetadata(context);
|
||||
|
||||
// Assert
|
||||
using(new CultureReplacer("en-US", "en-US"))
|
||||
using (new CultureReplacer("en-US", "en-US"))
|
||||
{
|
||||
Assert.Equal("name from localizer en-US", context.DisplayMetadata.DisplayName());
|
||||
Assert.Equal("description from localizer en-US", context.DisplayMetadata.Description());
|
||||
Assert.Equal("prompt from localizer en-US", context.DisplayMetadata.Placeholder());
|
||||
}
|
||||
using(new CultureReplacer("fr-FR", "fr-FR"))
|
||||
using (new CultureReplacer("fr-FR", "fr-FR"))
|
||||
{
|
||||
Assert.Equal("name from localizer fr-FR", context.DisplayMetadata.DisplayName());
|
||||
Assert.Equal("description from localizer fr-FR", context.DisplayMetadata.Description());
|
||||
|
|
@ -1031,12 +1031,12 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
// Assert
|
||||
var groupTwo = Assert.Single(enumNameAndGroup, e => e.Value.Equals("2", StringComparison.Ordinal));
|
||||
|
||||
using(new CultureReplacer("en-US", "en-US"))
|
||||
using (new CultureReplacer("en-US", "en-US"))
|
||||
{
|
||||
Assert.Equal("Loc_Two_Name", groupTwo.Key.Name);
|
||||
}
|
||||
|
||||
using(new CultureReplacer("fr-FR", "fr-FR"))
|
||||
using (new CultureReplacer("fr-FR", "fr-FR"))
|
||||
{
|
||||
Assert.Equal("Loc_Two_Name", groupTwo.Key.Name);
|
||||
}
|
||||
|
|
@ -1051,12 +1051,12 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
// Assert
|
||||
var groupTwo = Assert.Single(enumNameAndGroup, e => e.Value.Equals("2", StringComparison.Ordinal));
|
||||
|
||||
using(new CultureReplacer("en-US", "en-US"))
|
||||
using (new CultureReplacer("en-US", "en-US"))
|
||||
{
|
||||
Assert.Equal("Loc_Two_Name en-US", groupTwo.Key.Name);
|
||||
}
|
||||
|
||||
using(new CultureReplacer("fr-FR", "fr-FR"))
|
||||
using (new CultureReplacer("fr-FR", "fr-FR"))
|
||||
{
|
||||
Assert.Equal("Loc_Two_Name fr-FR", groupTwo.Key.Name);
|
||||
}
|
||||
|
|
@ -1071,12 +1071,12 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
// Assert
|
||||
var groupThree = Assert.Single(enumNameAndGroup, e => e.Value.Equals("3", StringComparison.Ordinal));
|
||||
|
||||
using(new CultureReplacer("en-US", "en-US"))
|
||||
using (new CultureReplacer("en-US", "en-US"))
|
||||
{
|
||||
Assert.Equal("type three name en-US", groupThree.Key.Name);
|
||||
}
|
||||
|
||||
using(new CultureReplacer("fr-FR", "fr-FR"))
|
||||
using (new CultureReplacer("fr-FR", "fr-FR"))
|
||||
{
|
||||
Assert.Equal("type three name fr-FR", groupThree.Key.Name);
|
||||
}
|
||||
|
|
@ -1091,12 +1091,12 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var groupThree = Assert.Single(enumNameAndGroup, e => e.Value.Equals("3", StringComparison.Ordinal));
|
||||
|
||||
// Assert
|
||||
using(new CultureReplacer("en-US", "en-US"))
|
||||
using (new CultureReplacer("en-US", "en-US"))
|
||||
{
|
||||
Assert.Equal("type three name en-US", groupThree.Key.Name);
|
||||
}
|
||||
|
||||
using(new CultureReplacer("fr-FR", "fr-FR"))
|
||||
using (new CultureReplacer("fr-FR", "fr-FR"))
|
||||
{
|
||||
Assert.Equal("type three name fr-FR", groupThree.Key.Name);
|
||||
}
|
||||
|
|
@ -1111,7 +1111,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var required = new RequiredAttribute();
|
||||
|
||||
var attributes = new Attribute[] { required };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
|
||||
// Act
|
||||
|
|
@ -1131,7 +1132,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var provider = CreateProvider();
|
||||
|
||||
var attributes = new Attribute[] { };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
context.ValidationMetadata.IsRequired = initialValue;
|
||||
|
||||
|
|
@ -1152,8 +1154,9 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
typeof(NullableReferenceTypes),
|
||||
typeof(NullableReferenceTypes).GetProperty(nameof(NullableReferenceTypes.NonNullableReferenceType)));
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(NullableReferenceTypes),
|
||||
nameof(NullableReferenceTypes.NonNullableReferenceType), typeof(string));
|
||||
typeof(NullableReferenceTypes).GetProperty(nameof(NullableReferenceTypes.NonNullableReferenceType)),
|
||||
typeof(string),
|
||||
typeof(NullableReferenceTypes));
|
||||
var context = new ValidationMetadataProviderContext(key, attributes);
|
||||
|
||||
// Act
|
||||
|
|
@ -1174,9 +1177,11 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var attributes = ModelAttributes.GetAttributesForProperty(
|
||||
typeof(NullableReferenceTypes),
|
||||
typeof(NullableReferenceTypes).GetProperty(nameof(NullableReferenceTypes.NonNullableReferenceTypeWithRequired)));
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(NullableReferenceTypes),
|
||||
nameof(NullableReferenceTypes.NonNullableReferenceTypeWithRequired), typeof(string));
|
||||
typeof(NullableReferenceTypes).GetProperty(nameof(NullableReferenceTypes.NonNullableReferenceTypeWithRequired)),
|
||||
typeof(string),
|
||||
typeof(NullableReferenceTypes));
|
||||
var context = new ValidationMetadataProviderContext(key, attributes);
|
||||
|
||||
// Act
|
||||
|
|
@ -1201,9 +1206,12 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var attributes = ModelAttributes.GetAttributesForProperty(
|
||||
typeof(NullableReferenceTypes),
|
||||
typeof(NullableReferenceTypes).GetProperty(nameof(NullableReferenceTypes.NonNullableReferenceType)));
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(NullableReferenceTypes),
|
||||
nameof(NullableReferenceTypes.NonNullableReferenceType), typeof(string));
|
||||
typeof(NullableReferenceTypes).GetProperty(nameof(NullableReferenceTypes.NonNullableReferenceType)),
|
||||
typeof(string),
|
||||
typeof(NullableReferenceTypes));
|
||||
|
||||
var context = new ValidationMetadataProviderContext(key, attributes);
|
||||
|
||||
// Act
|
||||
|
|
@ -1214,6 +1222,189 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
Assert.DoesNotContain(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(nameof(DerivedTypeWithAllNonNullProperties.Property1))]
|
||||
[InlineData(nameof(DerivedTypeWithAllNonNullProperties.Property2))]
|
||||
public void CreateValidationMetadata_InfersRequiredAttributeOnDerivedType_BaseAnDerivedTypHaveAllNonNullProperties(string propertyName)
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(DerivedTypeWithAllNonNullProperties);
|
||||
var property = modelType.GetProperty(propertyName);
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, modelType);
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// This test verifies how MVC reads the NullableContextOptions. We expect the property to not have a Nullable attribute on, and for
|
||||
// the types to have NullableContext. We'll encode our expectations as assertions so that we can catch if or when the compiler changes
|
||||
// this behavior and the test needs to be tweaked.
|
||||
Assert.False(DataAnnotationsMetadataProvider.HasNullableAttribute(context.PropertyAttributes, out _), "We do not expect NullableAttribute to be defined on the property");
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(context.ValidationMetadata.IsRequired);
|
||||
Assert.Contains(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationMetadata_InfersRequiredAttributeOnDerivedType_PropertyDeclaredOnBaseType()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(DerivedTypeWithAllNonNullProperties_WithNullableProperties);
|
||||
var property = modelType.GetProperty(nameof(DerivedTypeWithAllNonNullProperties_WithNullableProperties.Property1));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, modelType);
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(context.ValidationMetadata.IsRequired);
|
||||
Assert.Contains(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationMetadata_InfersRequiredAttributeOnDerivedType_NullablePropertyDeclaredOnDerviedType()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(DerivedTypeWithAllNonNullProperties_WithNullableProperties);
|
||||
var property = modelType.GetProperty(nameof(DerivedTypeWithAllNonNullProperties_WithNullableProperties.Property2));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, modelType);
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.Null(context.ValidationMetadata.IsRequired);
|
||||
Assert.DoesNotContain(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(nameof(DerivedTypeWithNullableProperties.Property1))]
|
||||
[InlineData(nameof(DerivedTypeWithNullableProperties.Property2))]
|
||||
public void CreateValidationMetadata_BaseAnDerivedTypHaveAllNullableProperties_DoesNotInferRequiredAttribute(string propertyName)
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(DerivedTypeWithNullableProperties);
|
||||
var property = modelType.GetProperty(propertyName);
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, modelType);
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.Null(context.ValidationMetadata.IsRequired);
|
||||
Assert.DoesNotContain(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationMetadata_InfersRequiredAttribute_BaseTypeIsNullable_PropertyIsNotNull()
|
||||
{
|
||||
// Tests the scenario listed in https://github.com/aspnet/AspNetCore/issues/14812
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(DerivedTypeWithNullableProperties_WithNonNullProperties);
|
||||
var property = modelType.GetProperty(nameof(DerivedTypeWithNullableProperties_WithNonNullProperties.Property2));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, modelType);
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(context.ValidationMetadata.IsRequired);
|
||||
Assert.Contains(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationMetadata_InfersRequiredAttribute_ShadowedPropertyIsNonNull()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(DerivedTypeWithNullableProperties_ShadowedProperty);
|
||||
var property = modelType.GetProperty(nameof(DerivedTypeWithNullableProperties_ShadowedProperty.Property1));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, modelType);
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(context.ValidationMetadata.IsRequired);
|
||||
Assert.Contains(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationMetadata_DoesNotInfersRequiredAttribute_TypeImplementingNonNullAbstractClass()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(TypeImplementIInterfaceWithNonNullProperty);
|
||||
var property = modelType.GetProperty(nameof(TypeImplementIInterfaceWithNonNullProperty.Property));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, modelType);
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(context.ValidationMetadata.IsRequired);
|
||||
Assert.Contains(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationMetadata_DoesNotInfersRequiredAttribute_TypeImplementingNonNullAbstractClass_NotNullable()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(TypeImplementIInterfaceWithNonNullProperty_AsNullable);
|
||||
var property = modelType.GetProperty(nameof(TypeImplementIInterfaceWithNonNullProperty_AsNullable.Property));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, modelType);
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.Null(context.ValidationMetadata.IsRequired);
|
||||
Assert.DoesNotContain(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationMetadata_WithOldModelIdentity_DoesNotInferValueBasedOnContext()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var modelType = typeof(TypeWithAllNonNullProperties);
|
||||
var property = modelType.GetProperty(nameof(TypeWithAllNonNullProperties.Property1));
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var key = ModelMetadataIdentity.ForProperty(property.PropertyType, property.Name, modelType);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
var context = new ValidationMetadataProviderContext(key, ModelAttributes.GetAttributesForProperty(modelType, property));
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.Null(context.ValidationMetadata.IsRequired);
|
||||
Assert.DoesNotContain(context.ValidationMetadata.ValidatorMetadata, m => m is RequiredAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationMetadata_WillAddValidationAttributes_From_ValidationProviderAttribute()
|
||||
{
|
||||
|
|
@ -1227,7 +1418,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
});
|
||||
|
||||
var attributes = new Attribute[] { new EmailAddressAttribute(), validationProviderAttribute };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(string), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
|
||||
// Act
|
||||
|
|
@ -1254,7 +1446,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var provider = CreateProvider();
|
||||
|
||||
var attributes = new Attribute[] { new RequiredAttribute() };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(string));
|
||||
var context = new BindingMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
context.BindingMetadata.IsBindingRequired = initialValue;
|
||||
|
||||
|
|
@ -1275,7 +1468,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var provider = CreateProvider();
|
||||
|
||||
var attributes = new Attribute[] { };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(string));
|
||||
var context = new BindingMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
context.BindingMetadata.IsReadOnly = initialValue;
|
||||
|
||||
|
|
@ -1294,7 +1488,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
|
||||
var attribute = new TestValidationAttribute();
|
||||
var attributes = new Attribute[] { attribute };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
|
||||
// Act
|
||||
|
|
@ -1313,7 +1508,29 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
|
||||
var attribute = new TestValidationAttribute();
|
||||
var attributes = new Attribute[] { attribute };
|
||||
var key = ModelMetadataIdentity.ForProperty(typeof(int), "Length", typeof(string));
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
context.ValidationMetadata.ValidatorMetadata.Add(attribute);
|
||||
|
||||
// Act
|
||||
provider.CreateValidationMetadata(context);
|
||||
|
||||
// Assert
|
||||
var validatorMetadata = Assert.Single(context.ValidationMetadata.ValidatorMetadata);
|
||||
Assert.Same(attribute, validatorMetadata);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateValidationDetails_ForProperty()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
var attribute = new TestValidationAttribute();
|
||||
var attributes = new Attribute[] { attribute };
|
||||
var property = typeof(string).GetProperty(nameof(string.Length));
|
||||
var key = ModelMetadataIdentity.ForProperty(property, typeof(int), typeof(string));
|
||||
var context = new ValidationMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
context.ValidationMetadata.ValidatorMetadata.Add(attribute);
|
||||
|
||||
|
|
@ -1479,7 +1696,7 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
|
||||
public bool Equals(KeyValuePair<EnumGroupAndName, string> x, KeyValuePair<EnumGroupAndName, string> y)
|
||||
{
|
||||
using(new CultureReplacer(string.Empty, string.Empty))
|
||||
using (new CultureReplacer(string.Empty, string.Empty))
|
||||
{
|
||||
return x.Key.Name.Equals(y.Key.Name, StringComparison.Ordinal)
|
||||
&& x.Key.Group.Equals(y.Key.Group, StringComparison.Ordinal);
|
||||
|
|
@ -1488,7 +1705,7 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
|
||||
public int GetHashCode(KeyValuePair<EnumGroupAndName, string> obj)
|
||||
{
|
||||
using(new CultureReplacer(string.Empty, string.Empty))
|
||||
using (new CultureReplacer(string.Empty, string.Empty))
|
||||
{
|
||||
return obj.Key.GetHashCode();
|
||||
}
|
||||
|
|
@ -1657,6 +1874,56 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TypeWithAllNonNullProperties
|
||||
{
|
||||
public string Property1 { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
private class DerivedTypeWithAllNonNullProperties : TypeWithAllNonNullProperties
|
||||
{
|
||||
public string Property2 { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
private class DerivedTypeWithAllNonNullProperties_WithNullableProperties : TypeWithAllNonNullProperties
|
||||
{
|
||||
public string? Property2 { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
private class TypeWithNullableProperties
|
||||
{
|
||||
public string? Property1 { get; set; }
|
||||
}
|
||||
|
||||
private class DerivedTypeWithNullableProperties : TypeWithNullableProperties
|
||||
{
|
||||
public string? Property2 { get; set; }
|
||||
}
|
||||
|
||||
private class DerivedTypeWithNullableProperties_WithNonNullProperties : TypeWithNullableProperties
|
||||
{
|
||||
public string Property2 { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
private class DerivedTypeWithNullableProperties_ShadowedProperty : TypeWithNullableProperties
|
||||
{
|
||||
public new string Property1 { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public abstract class AbstraceTypehNonNullProperty
|
||||
{
|
||||
public abstract string Property { get; set; }
|
||||
}
|
||||
|
||||
public class TypeImplementIInterfaceWithNonNullProperty : AbstraceTypehNonNullProperty
|
||||
{
|
||||
public override string Property { get; set; } = string.Empty;
|
||||
}
|
||||
#nullable restore
|
||||
|
||||
public class TypeImplementIInterfaceWithNonNullProperty_AsNullable : AbstraceTypehNonNullProperty
|
||||
{
|
||||
public override string Property { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
};
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(ClassWithDataMemberIsRequiredTrue).GetProperty(nameof(ClassWithDataMemberIsRequiredTrue.StringProperty)),
|
||||
typeof(string),
|
||||
nameof(ClassWithDataMemberIsRequiredTrue.StringProperty),
|
||||
typeof(ClassWithDataMemberIsRequiredTrue));
|
||||
var context = new BindingMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
|
||||
|
|
@ -50,8 +50,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
};
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(ClassWithDataMemberIsRequiredFalse).GetProperty(nameof(ClassWithDataMemberIsRequiredFalse.StringProperty)),
|
||||
typeof(string),
|
||||
nameof(ClassWithDataMemberIsRequiredFalse.StringProperty),
|
||||
typeof(ClassWithDataMemberIsRequiredFalse));
|
||||
var context = new BindingMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
|
||||
|
|
@ -98,8 +98,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var provider = new DataMemberRequiredBindingMetadataProvider();
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(ClassWithoutAttributes).GetProperty(nameof(ClassWithoutAttributes.StringProperty)),
|
||||
typeof(string),
|
||||
nameof(ClassWithoutAttributes.StringProperty),
|
||||
typeof(ClassWithoutAttributes));
|
||||
var context = new BindingMetadataProviderContext(key, GetModelAttributes(new object[0], new object[0]));
|
||||
|
||||
|
|
@ -126,8 +126,8 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
};
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(
|
||||
typeof(ClassWithDataMemberIsRequiredTrueWithoutDataContract).GetProperty(nameof(ClassWithDataMemberIsRequiredTrueWithoutDataContract.StringProperty)),
|
||||
typeof(string),
|
||||
nameof(ClassWithDataMemberIsRequiredTrueWithoutDataContract.StringProperty),
|
||||
typeof(ClassWithDataMemberIsRequiredTrueWithoutDataContract));
|
||||
var context = new BindingMetadataProviderContext(key, GetModelAttributes(new object[0], attributes));
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
var property = containerType.GetRuntimeProperty(propertyName);
|
||||
Assert.NotNull(property);
|
||||
|
||||
var key = ModelMetadataIdentity.ForProperty(property.PropertyType, propertyName, containerType);
|
||||
var key = ModelMetadataIdentity.ForProperty(property, property.PropertyType, containerType);
|
||||
|
||||
var builder = new MetadataBuilder(key);
|
||||
_detailsProvider.Builders.Add(builder);
|
||||
|
|
|
|||
Loading…
Reference in New Issue