在此处提出的最近一个问题中: ASP.NET MVC:数据注释验证是否足够?
...得出的结论是,依靠数据注释验证(由模型绑定器触发)不足以确保始终执行验证。我们仍然需要在服务层(或 ModelBinding 发生后的其他地方)添加相同的验证逻辑。不幸的是,我们将复制我们的验证代码(一次是使用数据注释,一次是在服务层)。服务层是否有一种简单的方法可以根据数据注释中定义的内容触发验证?如果这是可能的,那么我们将两全其美......我们不需要重复验证代码,但我们仍将确保验证始终被执行。
在此处提出的最近一个问题中: ASP.NET MVC:数据注释验证是否足够?
...得出的结论是,依靠数据注释验证(由模型绑定器触发)不足以确保始终执行验证。我们仍然需要在服务层(或 ModelBinding 发生后的其他地方)添加相同的验证逻辑。不幸的是,我们将复制我们的验证代码(一次是使用数据注释,一次是在服务层)。服务层是否有一种简单的方法可以根据数据注释中定义的内容触发验证?如果这是可能的,那么我们将两全其美......我们不需要重复验证代码,但我们仍将确保验证始终被执行。
在这个博客的帮助下:http: //goneale.com/2009/03/04/using-metadatatype-attribute-with-aspnet-mvc-xval-validation-framework/ 我能够创建一个方法来测试我的基于数据注释定义的验证的对象。它将执行从 ValidateAttribute 派生的任何验证属性。我现在可以将我的对象从我的服务层(或 DomainModel)传递给这个方法,并且我的服务层不再依赖于控制器。这将确保在将数据持久化到数据库之前始终执行验证。我无法按原样使用博客上的代码,因为我似乎无法访问 Graham 使用的一些扩展方法,所以这是我的版本:
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();
}
此代码适用于有和没有伙伴类的两个类,但如果您不使用伙伴类,则可以稍微简化此代码。希望这个对你有帮助。
你没有检查我在上一个问题中的答案吗?
我提交了一些基于 DTO 的 DataAnnotation 属性进行自动验证的代码。只要您的 DTO 在您的控制器操作的参数中使用,它们就会被此属性拾取并无论如何都经过验证。
唯一的问题是:如何生成 DTO?
如果你可以控制你的 DTO 类的生成,那么你也可以为它们添加额外的接口。我发布的代码使用 T4 over EF、xVal 和 DataAnnotation 以及声明Validate()
在每个实体类中实现的方法的自定义接口。
我想达到同样的效果并尝试了约翰尼的回答。在您拥有与其他属性相关的验证之前,它可以正常工作,例如使用 RequiredIf 属性。
我最终使用了 System.ComponentModel.DataAnnotations 中的 Validator 类,它实际上是为此而设计的,并且应该应用与通常应用完全相同的完整逻辑。
这是向您展示如何使用 Validator 类执行此操作的示例方法。
public static bool TryValidate(object obj, List<ValidationResult> results = null)
{
var context = new ValidationContext(obj, serviceProvider: null, items: null);
return Validator.TryValidateObject(obj, context, results, true);
}