我正在使用VS2008 SP1,WCF Ria Service 2009年7月CTP。我发现MetadataType在部分类模式下不起作用,真的不知道我错过了什么:
工作: -
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();
}
}
}
不工作
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();
}
}
}
答案 0 :(得分:9)
编辑:我在这里找到答案:http://forums.silverlight.net/forums/p/149264/377212.aspx
在验证之前,您需要手动注册元数据类:
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);
(原始答案如下)
问题不在于您的部分类,而是Validator.TryValidateObject似乎无法识别MetaDataType属性。我有同样的问题 - MVC 2中的内置验证识别元数据类,但TryValidateObject没有。
见这些: Validating DataAnnotations with Validator class Validation does not work when I use Validator.TryValidateObject
作为旁注,我不知道是否有必要,但我在元数据类中看到的所有示例都在每个属性上使用默认的get / set:
[Required(AllowEmptyStrings=false, ErrorMessage="Name required entry")]
[StringLength(3)]
public string Name { get; set; }
答案 1 :(得分:2)
非常感谢Jeremy Gruenwald上面给出的答案......我完全被这个问题困住了。
我想基于这个解决方案创建一个标准的验证类,但我不想传递元数据类类型,因为它感觉很难看。
为了实现这一点,我创建了一个静态类,它对自定义属性进行查找以获取元数据类类型,然后在返回验证结果之前注册该类。
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;
}
}
}
用法很简单:
var errors = EntityValidator.Validate(myEntity);
答案 2 :(得分:0)
如果您正在使用WPF和EF,这一直对我有用......
[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;
}
}
实现它的基类......
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
}