С помощью этого блога: http://goneale.com/2009/03/04/using-metadatatype-attribute-with-aspnet-mvc-xval-validation-framework/
Мне удалось создать метод, который будет проверять мой объект на основе проверок, определенных аннотациями данных. Он выполнит любой атрибут проверки, полученный из ValidateAttribute. Теперь я могу передать свой объект этому методу из моего сервисного уровня (или DomainModel), и мой сервисный уровень больше не зависит от контроллера. Это гарантирует, что проверка всегда будет выполняться до сохранения данных в базе данных. Я не мог использовать код в блоге как есть, так как у меня, похоже, нет доступа к некоторым методам расширения, которые использовал Грэм, поэтому вот моя версия:
public static IList<KeyValuePair<string, string>> GetErrors(object obj)
{
// get the name of the buddy class for obj
MetadataTypeAttribute metadataAttrib = obj.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault() as MetadataTypeAttribute;
// if metadataAttrib is null, then obj doesn't have a buddy class, and in such a case, we'll work with the model class
Type buddyClassOrModelClass = metadataAttrib != null ? metadataAttrib.MetadataClassType : obj.GetType();
var buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass).Cast<PropertyDescriptor>();
var modelClassProperties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();
var errors = from buddyProp in buddyClassProperties
join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name // as this is an inner join, it will return only the properties that are in both the buddy and model classes
from attribute in buddyProp.Attributes.OfType<ValidationAttribute>() // get only the attributes of type ValidationAttribute
where !attribute.IsValid(modelProp.GetValue(obj))
select new KeyValuePair<string, string>(buddyProp.Name, attribute.FormatErrorMessage(string.Empty));
return errors.ToList();
}
Этот код работает с обоими классами, которые имеют и не имеют классов собеседников, хотя если вы не используете классы собеседников, этот код можно немного упростить.
Я надеюсь, что вы найдете это полезным.