MetadataType problem

后端 未结 3 490
别跟我提以往
别跟我提以往 2020-12-01 23:15

I\'m using VS2008 SP1, WCF Ria Service July 2009 CTP. I found out that MetadataType does not work in partial class mode, really don\'t know what I have missed out:

W

相关标签:
3条回答
  • If you are working with WPF and EF, this has always worked for me...

    [MetadataType(typeof(Department.Metadata))]
    public partial class Department : BaseModel
    {
        static Department()
        {
            TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Department),typeof(Metadata)), typeof(Department));
        }
        private sealed class Metadata
        {
            [Required(AllowEmptyStrings = false, ErrorMessage = "Department Name is required.")]
            [StringLength(50, ErrorMessage = "Name must be between 3 and 50 characters.", MinimumLength = 3)]
            public string Name;
    
            [StringLength(250, ErrorMessage = "Name must be between 10 and 250 characters.", MinimumLength = 10)]
            public string Description;
        }
    }
    

    And the base class that makes it happen...

    public abstract class BaseModel : IDataErrorInfo
    {
        #region Validation
        string IDataErrorInfo.Error
        {
            get { return null; }
        }
        string IDataErrorInfo.this[string propertyName]
        {
            get
            {
                var propertyInfo = GetType().GetProperty(propertyName);
                var results = new List<ValidationResult>();
                var result = Validator.TryValidateProperty(propertyInfo.GetValue(this, null), new ValidationContext(this, null, null)
                {
                    MemberName = propertyName
                }, results);
    
                if (result) return string.Empty;
                var validationResult = results.First();
                return validationResult.ErrorMessage;
            }
        }
        #endregion
    }
    
    0 讨论(0)
  • 2020-12-01 23:32

    Many thanks to Jeremy Gruenwald for the answer above... I was completely stuck on this one.

    I wanted to create a standard validation class based on this solution, but I didn't want to have to pass in the metadata class type because it just felt ugly.

    To achieve this I created a static class which does a lookup on the custom attributes to get the metadata class type and then registers that class before returning the validation results.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    
    namespace MyApp.Validation
    {
        public static class EntityValidator
        {
            public static List<ValidationResult> Validate(object instance, bool validateAllProperties = true)
            {
                RegisterMetadataClass(instance);
    
                var validationContext = new ValidationContext(instance, null, null);
                var validationResults = new List<ValidationResult>();
    
                Validator.TryValidateObject(instance, validationContext, validationResults, validateAllProperties);
    
                return validationResults;
            }
    
            private static void RegisterMetadataClass(object instance)
            {
                var modelType = instance.GetType();
                var metadataType = GetMetadataType(modelType);
    
                if (metadataType != null) 
                {
                    TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(modelType, metadataType), modelType);
                }
            }
    
            private static Type GetMetadataType(Type type)
            {
                var attribute = (MetadataTypeAttribute)type.GetCustomAttributes(typeof (MetadataTypeAttribute), true).FirstOrDefault();
                return attribute == null ? null : attribute.MetadataClassType;
            }
        }
    }
    

    usage is a simple as:

    var errors = EntityValidator.Validate(myEntity);
    
    0 讨论(0)
  • 2020-12-01 23:35

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

    Before validating, you need to manually register the metadata class:

    TypeDescriptor.AddProviderTransparent(
                new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Person), typeof(PersonMetadata)), typeof(Person));
    
            List<ValidationResult> res = new List<ValidationResult>();
            bool valid = Validator.TryValidateObject(p, new ValidationContext(p, null, null), res, true);
    

    (Original answer follows)

    The problem isn't specifically with your partial class, it's that Validator.TryValidateObject doesn't seem to recognize the MetaDataType attribute. I have the same problem - the built-in validation in MVC 2 recognizes the metadata class, but TryValidateObject doesn't.

    See these: Validating DataAnnotations with Validator class Validation does not work when I use Validator.TryValidateObject

    As a side note, I don't know if it's necessary, but all examples I've seen for metadata classes employ the default get/set on each property:

    [Required(AllowEmptyStrings=false, ErrorMessage="Name required entry")]
    [StringLength(3)]
    public string Name { get; set; }
    
    0 讨论(0)
提交回复
热议问题