9

DataAnnotations不適用於好友類。以下代碼總是驗證爲真。爲什麼?當我使用Validator.TryValidateObject時,驗證不起作用

var isValid = Validator.TryValidateObject(new Customer(),Context,results,true);

這裏是好友類。

public partial class Customer 
{ 
    public string Name { get; set; } 
    public int Age { get; set; } 
} 

[MetadataType(typeof(CustomerMetaData))] 
public partial class Customer 
{ 
    public class CustomerMetaData 
    { 
     [Required(ErrorMessage = "You must supply a name for a customer.")]   
     public string Name { get; set; } 
    } 
} 

這是另一個有同樣問題的線程,但沒有答案。 link text

+0

我對此不太確定,但我認爲您不應該嵌套這些類。此外,我認爲這可能會使CustomMetaData類無法訪問公共關鍵字。嘗試將CustomerMetaData移出客戶類並公開。 – Alxandr 2010-03-11 01:56:41

+0

即使將CustomerMetaData移出Customer類並聲明爲公共,它也不起作用。 TryValidateObject支持buddyclass(MetadataType)嗎? – ashraf 2010-03-11 02:10:53

回答

27

我找到了答案在這裏:http://forums.silverlight.net/forums/p/149264/377212.aspx

MVC識別MetaDataType屬性,但其他項目沒有。驗證之前,您需要手動註冊元數據類:

TypeDescriptor.AddProviderTransparent(
      new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Customer), typeof(CustomerMetadata)), typeof(Customer)); 

var isValid = Validator.TryValidateObject(new Customer(), context, results, true); 
+1

謝謝。如果我選擇數據註釋作爲我的驗證框架,那麼Validator.TryValidaeObject應該從任何地方進行驗證。 – ashraf 2010-03-18 15:53:38

+0

感謝您的好回答! +1 – Karamafrooz 2016-03-16 11:18:46

+0

對於AssociatedMetadataTypeTypeDescriptionProvider類,沒有構造函數重載需要三個參數。我在代碼片段中看到了這個問題。 – RBT 2016-05-21 23:16:44

1

雖然我沒有測試在.NET 4.0的代碼,在.NET 3.5/Silverlight 3中,元數據類應該是這樣的:

[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

不,它仍然無法工作。我認爲這是一個錯誤。 – ashraf 2010-03-11 17:10:53

4

經過一番研究,我找不到任何如果我使用MetadataType(好友類),TryValidateObject總是返回true的原因。但它適用於下面的代碼(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; 
    } 
1

還有一種情況MetadataType屬性沒有被對象上下文識別的問題。雖然可以手動驗證之前添加類型描述: TypeDescriptor.AddProviderTransparent( new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Customer), typeof(CustomerMetaData)), typeof(Customer));

更簡潔的方式來處理這將是更新的實體模型.TT文件,下面添加到每個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); 
    } 

這將允許您將屬性添加到部分類:

[MetadataType(typeof(CustomerMetaData))] 
public partial class Customer 
{ 

} 

public partial class CustomerMetaData 
{ 
    [Required] 
    public string CustomerName { get; set; } 
} 
+0

您好@Gareth Suarez,我認爲這是一個好主意,您能否提供更多關於如何編輯Entity Model.tt文件的信息? – 2014-09-23 03:11:08

+1

我其實試過這樣做,但我不知道應該在哪裏包含您的代碼段。我試圖將它包含在每個DTO的構造函數中,但我根本沒有運氣。任何想法?順便說一句,我想通過MetadataType在一些屬性中設置IgnoreDataMember,這種方法應該可以,對吧? – 2014-09-23 03:26:19