Я нашел много информации о реализации настраиваемого связывателя модели для целей проверки, но я мало что видел о том, что я ' m пытается сделать.
Я хочу иметь возможность манипулировать значениями, которые связыватель модели собирается установить на основе атрибутов свойства в модели представления. Например:
public class FooViewModel : ViewModel
{
[AddBar]
public string Name { get; set; }
}
AddBar - это просто
public class AddBarAttribute : System.Attribute
{
}
Мне не удалось найти чистый способ найти атрибуты свойства модели представления в методе BindModel настраиваемого связывателя модели. Это работает, но похоже, что должно быть более простое решение:
public class FooBarModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = base.BindModel(controllerContext, bindingContext);
var hasBarAttribute = false;
if(bindingContext.ModelMetadata.ContainerType != null)
{
var property = bindingContext.ModelMetadata.ContainerType.GetProperties()
.Where(x => x.Name == bindingContext.ModelMetadata.PropertyName).FirstOrDefault();
hasBarAttribute = property != null && property.GetCustomAttributes(true).Where(x => x.GetType() == typeof(AddBarAttribute)).Count() > 0;
}
if(value.GetType() == typeof(String) && hasBarAttribute)
value = ((string)value) + "Bar";
return value;
}
}
Есть ли более чистый способ просмотра атрибутов в свойстве модели представления или другой тип атрибута, который я мог бы использовать? Атрибуты DataAnnotation действительно, похоже, предназначены для другой проблемы.
ОБНОВЛЕНИЕ
Ответ Крейга привел меня в нужное место, но я подумал, что приведу здесь несколько примеров для других.
Поставщик метаданных, которым я оказался с выглядит как
public class FooBarModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
var metaData = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
if(attributes.OfType<AddBarAttribute>().Any())
metaData.AdditionalValues.Add("AddBarKey", true);
return metaData;
}
}
Папка модели выглядит так:
public class FooBarModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = base.BindModel(controllerContext, bindingContext);
if(bindingContext.ModelMetadata.AdditionalValues.ContainsKey("AddBarKey"))
value = ((string)value) + "Bar";
return value;
}
}