Ich verwende den folgenden Ansatz, um automatisch Datenanmerkungen von meinen Entitäten in mein Ansichtsmodell zu kopieren. Dies stellt sicher, dass Dinge wie StringLength und Required für Entity/ViewModel immer gleich sind.
Es funktioniert mit der Automapper-Konfiguration, funktioniert also, wenn die Eigenschaften im Viewmodel unterschiedlich benannt sind, solange AutoMapper richtig eingerichtet ist.
Sie müssen einen benutzerdefinierten ModelValidatorProvider und einen benutzerdefinierten ModelMetadataProvider erstellen, damit dies funktioniert. Meine Erinnerung an warum ist ein wenig neblig, aber ich glaube, dass es sowohl serverseitige und clientseitige Validierungsarbeiten sind, als auch jede andere Formatierung, die Sie basierend auf den Metadaten vornehmen (zB ein Stern neben den erforderlichen Feldern).
Hinweis: Ich habe meinen Code leicht vereinfacht, da ich ihn unten hinzugefügt habe, daher kann es einige kleine Probleme geben.
Metadaten-Anbieter
public class MetadataProvider : DataAnnotationsModelMetadataProvider
{
private IConfigurationProvider _mapper;
public MetadataProvider(IConfigurationProvider mapper)
{
_mapper = mapper;
}
protected override System.Web.Mvc.ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
//Grab attributes from the entity columns and copy them to the view model
var mappedAttributes = _mapper.GetMappedAttributes(containerType, propertyName, attributes);
return base.CreateMetadata(mappedAttributes, containerType, modelAccessor, modelType, propertyName);
}
}
Validator Provivder
public class ValidatorProvider : DataAnnotationsModelValidatorProvider
{
private IConfigurationProvider _mapper;
public ValidatorProvider(IConfigurationProvider mapper)
{
_mapper = mapper;
}
protected override System.Collections.Generic.IEnumerable<ModelValidator> GetValidators(System.Web.Mvc.ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
var mappedAttributes = _mapper.GetMappedAttributes(metadata.ContainerType, metadata.PropertyName, attributes);
return base.GetValidators(metadata, context, mappedAttributes);
}
}
Helper oben beschriebene Methode 2 Klassen
public static IEnumerable<Attribute> GetMappedAttributes(this IConfigurationProvider mapper, Type sourceType, string propertyName, IEnumerable<Attribute> existingAttributes)
{
if (sourceType != null)
{
foreach (var typeMap in mapper.GetAllTypeMaps().Where(i => i.SourceType == sourceType))
{
foreach (var propertyMap in typeMap.GetPropertyMaps())
{
if (propertyMap.IsIgnored() || propertyMap.SourceMember == null)
continue;
if (propertyMap.SourceMember.Name == propertyName)
{
foreach (ValidationAttribute attribute in propertyMap.DestinationProperty.GetCustomAttributes(typeof(ValidationAttribute), true))
{
if (!existingAttributes.Any(i => i.GetType() == attribute.GetType()))
yield return attribute;
}
}
}
}
}
if (existingAttributes != null)
{
foreach (var attribute in existingAttributes)
{
yield return attribute;
}
}
}
Referenced in Hinweise
Andere
- Wenn Sie Dependency Injection verwenden, stellen Sie sicher, dass Ihr Behälter nicht bereits mit dem eingebauten Metadaten-Anbieter oder Validator Anbieter zu ersetzen. In meinem Fall benutzte ich das Ninject.MVC3-Paket, das einen von ihnen gebunden hat, nachdem ich den Kernel erstellt hatte, und musste ihn anschließend erneut binden, so dass meine Klasse tatsächlich verwendet wurde. Ich bekam Ausnahmen von Required, die nur einmal hinzugefügt werden durften, brauchte den größten Teil eines Tages, um es aufzuspüren.
zeigen einige Code, so können wir sehen, was Sie tun. – rboarman