He encontrado mucha información sobre la implementación de un archivador de modelo personalizado con fines de validación, pero no he visto mucho sobre lo que estoy tratando de hacer.Encontrar atributos personalizados en las propiedades del modelo de vista cuando se vincula el modelo
Quiero ser capaz de manipular los valores que el archivador modelo va a establecer en función de los atributos en la propiedad en el modelo de vista. Por ejemplo:
public class FooViewModel : ViewModel
{
[AddBar]
public string Name { get; set; }
}
AddBar es sólo
public class AddBarAttribute : System.Attribute
{
}
no he sido capaz de encontrar una manera limpia para encontrar los atributos de una propiedad vista del modelo en el método bindModel el modelo de carpeta de encargo. Esto funciona, pero se siente que debe haber una solución más simple:
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;
}
}
¿Hay una manera más limpia para ver los atributos de la propiedad vista del modelo o de otro tipo de atributo que pudiera utilizar? Los atributos de DataAnnotation realmente parecen ser para un problema diferente.
ACTUALIZACIÓN
respuesta de Craig me llegó al lugar correcto, pero pensé que había puesto algunos ejemplos aquí para otros.
El proveedor de metadatos que terminó con miradas como
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;
}
}
El modelo ligante se parece a:
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;
}
}
Pensé que tenía sentido después de seguir su enlace, pero ahora no estoy tan seguro. En realidad, no quiero cambiar los valores de ninguna de las propiedades de anotación de datos tanto como cambiar el valor del modelo en sí en función de una nueva propiedad (al agregar "Barra" al final del ejemplo anterior). Llamar a metaData.Model + = "Barra" no parece tener ningún efecto en nada. – Jared
Después de haber agregado sus tokens personalizados a los metadatos del modelo, puede cambiar el encuadernador del modelo para que los reconozca. –
Gracias por el puntero. Actualicé la publicación principal con algunos ejemplos basados en el enlace que compartiste. – Jared