The GetMetadataForProperty()
is declared on the class ModelMetadataProvider
.
AssociatedMetadataProvider
derives from ModelMetadataProvider
. CreateMetadata()
is declared on AssociatedMetadataProvider
. The DataAnnotationsMetadataProvider
that is overridden in the link you provide is derived from AssociatedMetadataProvider
.
The MVC framework makes calls to ModelMetadataProvider
's GetMetadataForProperty()
method.
The reason overriding CreateMetadata()
is working for you is because the AssociatedModelMetadataProvider
's default implementation of GetMetadataForProperty()
makes a call to CreateMetadata()
. It looks like this:
public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName)
{
if (containerType == null)
{
throw new ArgumentNullException("containerType");
}
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "propertyName");
}
PropertyDescriptor propertyDescriptor = this.GetTypeDescriptor(containerType).GetProperties().Find(propertyName, true);
if (propertyDescriptor == null)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MvcResources.Common_PropertyNotFound, new object[] { containerType.FullName, propertyName }));
}
return this.GetMetadataForProperty(modelAccessor, containerType, propertyDescriptor);
}
protected virtual ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, PropertyDescriptor propertyDescriptor)
{
IEnumerable<Attribute> attributes = this.FilterAttributes(containerType, propertyDescriptor, propertyDescriptor.Attributes.Cast<Attribute>());
return this.CreateMetadata(attributes, containerType, modelAccessor, propertyDescriptor.PropertyType, propertyDescriptor.Name);
}
If you are subclassing the AssociatedMetadataProvider
as you are in the link you provided, then your preferred extensibility point is the CreateMetadata
method, because the AssociatedMetadataProvider.GetMetadataForProperty()
method pre-validates the contract of your CreateMetadata()
method. That way, you know that if there is an error in your CreateMetadata()
method, you already know that the source of the error is in your method and not in the arguments that were passed to it.
Also, here is the source of the FilterAttributes()
method, in case you were wondering:
protected virtual IEnumerable<Attribute> FilterAttributes(Type containerType, PropertyDescriptor propertyDescriptor, IEnumerable<Attribute> attributes)
{
if (!typeof(ViewPage).IsAssignableFrom(containerType) && !typeof(ViewUserControl).IsAssignableFrom(containerType))
{
return attributes;
}
return attributes.Where<Attribute>(delegate (Attribute a) {
return !(a is ReadOnlyAttribute);
});
}