Validation does not work when I use Validator.TryValidateObject

前端 未结 4 1615
盖世英雄少女心
盖世英雄少女心 2020-11-30 07:56

DataAnnotations does not work with buddy class. The following code always validate true. Why ?

var isValid = Validator.TryValidateObject(new Customer(), Context, res

相关标签:
4条回答
  • 2020-11-30 08:46

    Although I did not test your code in .NET 4.0, in .NET 3.5 / Silverlight 3, your metadata class should look like this:

    [MetadataType(typeof(Customer.CustomerMetaData))]
    public partial class Customer 
    { 
        internal sealed class CustomerMetaData 
        {
            private CustomerMetaData()
            {
            }
    
            [Required(ErrorMessage = "You must supply a name for a customer.")]        
            public string Name; 
        } 
    }
    
    0 讨论(0)
  • 2020-11-30 08:51

    There is an issue where the MetadataType attribute is not being recognized by the object context. While you can manually add the type descriptor before validation: TypeDescriptor.AddProviderTransparent( new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Customer), typeof(CustomerMetaData)), typeof(Customer));

    a more concise way to handle it would be to update the Entity Model .tt file, to add the following to each DTO:

        Type currentType = MethodBase.GetCurrentMethod().DeclaringType;
        object[] attributes = currentType.GetCustomAttributes(typeof(MetadataTypeAttribute),false);
        if(attributes.Length > 0)
        {
            //MetadataType attribute found!
            MetadataTypeAttribute metaDataAttribute = (MetadataTypeAttribute)attributes[0];
            TypeDescriptor.AddProviderTransparent(
                new AssociatedMetadataTypeTypeDescriptionProvider(
                    currentType, metaDataAttribute.MetadataClassType),currentType);
        }
    

    This will allow you to add the attributes to the partial classes:

    [MetadataType(typeof(CustomerMetaData))]
    public partial class Customer
    {
    
    }
    
    public partial class CustomerMetaData
    {
        [Required]
        public string CustomerName { get; set; }
    }
    
    0 讨论(0)
  • 2020-11-30 08:58

    I found the answer here: http://forums.silverlight.net/forums/p/149264/377212.aspx

    MVC recognizes the MetaDataType attribute, but other projects do not. Before validating, you need to manually register the metadata class:

    TypeDescriptor.AddProviderTransparent(
                new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Customer), typeof(CustomerMetadata)), typeof(Customer));
    
    var isValid = Validator.TryValidateObject(new Customer(), context, results, true);
    
    0 讨论(0)
  • 2020-11-30 09:00

    After some research I couldn't find any reason why TryValidateObject always return true if I use MetadataType (buddy class). But it works with the following code (xVal).

        public static IEnumerable<ErrorInfo> GetErrors(object instance, string name)
        {
            var metadataAttrib = instance.GetType()
                    .GetCustomAttributes(typeof(MetadataTypeAttribute), true)
                    .OfType<MetadataTypeAttribute>().FirstOrDefault();
            var buddyClassOrModelClass = metadataAttrib != null
                    ? metadataAttrib.MetadataClassType
                    : instance.GetType();
            var buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass)
                .Cast<PropertyDescriptor>();
            var modelClassProperties = TypeDescriptor.GetProperties(instance.GetType())
                .Cast<PropertyDescriptor>();
    
            var list = from buddyProp in buddyClassProperties
                       join modelProp in modelClassProperties on
                                buddyProp.Name equals modelProp.Name
                       from attribute in buddyProp.Attributes.OfType<ValidationAttribute>()
                       where !attribute.IsValid(modelProp.GetValue(instance))
                       select new ErrorInfo(
                           buddyProp.Name,
                           attribute.FormatErrorMessage(modelProp.Name),
                           instance);
    
            if (name != null)
                list = list.Where(x => x.PropertyName == name);
    
            return list;
        }
    
    0 讨论(0)
提交回复
热议问题