代码之家  ›  专栏  ›  技术社区  ›  Johnny Oshika

ASP.NET MVC:如何在服务层执行数据注释验证?

  •  2
  • Johnny Oshika  · 技术社区  · 17 年前

    在这里最近提出的一个问题中: ASP.NET MVC: Is Data Annotation Validation Enough?

    …得出的结论是,依靠数据注释验证(由模型绑定器触发)不足以确保始终执行验证。我们仍然需要在服务层(或者在模型绑定发生后的其他地方)添加相同的验证逻辑。不幸的是,我们将复制我们的验证代码(一次是使用数据注释,另一次是在服务层)。服务层是否有一种简单的方法可以根据数据注释中定义的内容触发验证?如果这是可能的,那么我们将两全其美……我们不需要重复验证代码,但我们仍将确保始终执行验证。

    3 回复  |  直到 9 年前
        1
  •  4
  •   Johnny Oshika    17 年前

    在本博客的帮助下: 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();
        }
    

    这段代码适用于有和没有好友类的两个类,尽管如果不使用好友类,这段代码可以简化一点。 我希望你觉得这有用。

        2
  •  0
  •   Community Mohan Dere    9 年前

    my answer 在你之前的问题中?

    唯一的问题是:如何生成DTO?

    1. 您是否使用EF或类似产品?

    如果您可以控制DTO类的生成,那么您还可以向它们添加一个附加接口。我发布的代码使用T4 over EF、xVal和DataAnnotation以及声明 Validate() 方法,该方法在每个实体类中实现。

        3
  •  0
  •   Dacker    9 年前

    最后,我在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);
        }