Reproduction:
Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations
Module Module1
Sub Main()
Dim type = GetType(Contact)
TypeDescriptor.AddProviderTransparent(
New AssociatedMetadataTypeTypeDescriptionProvider(type), type)
Dim contact As New Contact
Dim context As New ValidationContext(contact, Nothing, Nothing)
Dim errors As New List(Of ValidationResult)
Dim result = Validator.TryValidateObject(contact, context, errors, True)
End Sub
End Module
<CustomValidation(GetType(Contact.ContactMd), "*********************")>
<MetadataType(GetType(Contact.ContactMd))>
Public Class Contact
Public Property Email As String
Public Property EmailRepeat As String
Public Class ContactMd
'<Required()>
Public Property Email
'<Required()>
Public Property EmailRepeat
Public Shared Function ValidateEmails(ByVal contact As Contact) _
As ValidationResult
Return If(contact.Email = contact.EmailRepeat,
ValidationResult.Success,
New ValidationResult("Fail!"))
End Function
End Class
End Class
The above code will throw an exception:
The CustomValidationAttribute method '*********************' does not exist in type 'ContactMd' or is not public and static.
This exception is justified and it's a sign that things are working.
Once I uncomment the Required
attributes on the properties in the Md class, the exception will not be throw, which means, the validation system doesn't validate for both property-typed attributes and class-level attributes.
Any workaround?
The answer is, that the validation system validates the property validation attributes first (the
Required
attributes in this case), and will only proceed to theCustomValidationAttribute
if the object passed the property attributes.So per the reproduction above, changing the line
to something like (allowing the enitity to pass the property validation):
Will throw the expected exception.