Problem with metadata

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

Job: -

public partial class Person { private string _Name; [Required(AllowEmptyStrings=false, ErrorMessage="Name required entry")] [StringLength(3)] public string Name { set{_Name = value;} get{return _Name;} } } class Program { static void Main(string[] args) { Person p = new Person { Name="123432" }; List res = new List(); Validator.TryValidateObject(p,new ValidationContext(p,null,null), res,true); if (res.Count > 0) { Console.WriteLine(res[0].ErrorMessage); Console.ReadLine(); } } } 

Does not work

 public partial class Person { private string _Name; public string Name { set{_Name = value;} get{return _Name;} } } [MetadataType(typeof(PersonMetadata))] public partial class Person { } public partial class PersonMetadata { [Required(AllowEmptyStrings=false, ErrorMessage="Name required entry")] [StringLength(3)] public string Name; } class Program { static void Main(string[] args) { Person p = new Person { Name="123432" }; List res = new List(); Validator.TryValidateObject(p,new ValidationContext(p,null,null), res,true); if (res.Count > 0) { Console.WriteLine(res[0].ErrorMessage); Console.ReadLine(); } } } 
+3
source share
3 answers

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

Before validation, you must 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 is not related to your partial class, so Validator.TryValidateObject does not seem to recognize the MetaDataType attribute. I have the same problem: the built-in check in MVC 2 recognizes the metadata class, but TryValidateObject does not.

See: Validating DataAnnotations with the Validator Class Validation does not work when I use Validator.TryValidateObject

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

 [Required(AllowEmptyStrings=false, ErrorMessage="Name required entry")] [StringLength(3)] public string Name { get; set; } 
+9
source

Many thanks to Jeremy Grunwald for the answer above ... I am completely stuck on this.

I wanted to create a standard validation class based on this solution, but I did not want to go through the metadata class class because it just felt ugly.

To do this, I created a static class that searches for user attributes to get the type of the metadata class, and then registers this 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; } } } 

use is simple as:

 var errors = EntityValidator.Validate(myEntity); 
+2
source

If you work with WPF and EF, this 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 does this ...

 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
source

All Articles