/// <summary> /// Creates a <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>. /// </summary> /// <param name="propertyInfo">The <see cref="PropertyInfo"/>.</param> /// <returns>A <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.</returns> internal PropertyModel CreatePropertyModel(PropertyInfo propertyInfo) { if (propertyInfo == null) { throw new ArgumentNullException(nameof(propertyInfo)); } var attributes = propertyInfo.GetCustomAttributes(inherit: true); // BindingInfo for properties can be either specified by decorating the property with binding specific attributes. // ModelMetadata also adds information from the property's type and any configured IBindingMetadataProvider. var modelMetadata = _modelMetadataProvider.GetMetadataForProperty(propertyInfo.DeclaringType, propertyInfo.Name); var bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata); if (bindingInfo == null) { // Look for BindPropertiesAttribute on the handler type if no BindingInfo was inferred for the property. // This allows a user to enable model binding on properties by decorating the controller type with BindPropertiesAttribute. var declaringType = propertyInfo.DeclaringType; var bindPropertiesAttribute = declaringType.GetCustomAttribute <BindPropertiesAttribute>(inherit: true); if (bindPropertiesAttribute != null) { var requestPredicate = bindPropertiesAttribute.SupportsGet ? _supportsAllRequests : _supportsNonGetRequests; bindingInfo = new BindingInfo { RequestPredicate = requestPredicate, }; } } var propertyModel = new PropertyModel(propertyInfo, attributes) { PropertyName = propertyInfo.Name, BindingInfo = bindingInfo, }; return(propertyModel); }