问题
I have a [EmailAddress]
DataAnnotation from .net 4.5 on a model property, which returns a 'The Email field is not a valid e-mail address.' error during validation, when the Email property is empty.
While this is technically true, I would have expected this empty value to only be caught with a [Required]
annotation.
Is there any parameter I'm missing which can be passed to the [EmailAddress]
annotation to allow empty strings to validate, or do I have to fall back to using a custom validator regular expression?
回答1:
There is no such parameter for EmailAddressAttribute
. The validation code for this attibute is following:
if (value == null)
{
return true;
}
string input = value as string;
return ((input != null) && (_regex.Match(input).Length > 0));
And the regex is defined as (there will be no match for empty string):
_regex = new Regex(@"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$", RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);
To achieve your goal you can create your can inherit from DataTypeAttribute
override IsValid
method, so it will return true
for empty or null strings and use instance of EmailAddressAttribute
. This should be something like this:
public override bool IsValid(object value)
{
if (value == null)
{
return true;
}
string input = value as string;
var emailAddressAttribute = new EmailAddressAttribute();
return (input != null) && (string.IsNullOrEmpty(input) || emailAddressAttribute.IsValid(input));
}
回答2:
Other way is to just call API differently.
For JSON ask caller to provide "Email": null
or don't include this property in the body. For XML ask caller who is providing empty element <Email></Email>
to remove this element from message body if email is not available.
If JSON property is null or not present or XML element not present, the field in your model becomes null and thus won't throw validation error because is just not present unless you have [Required]
added. This way you drive required or not.
I do understand in some instances "lazy" or unable caller may want to always send same body with empty value, especially for XML. "I'm sending this <Email></Email>
because my customer didn't provide me the email"
来源:https://stackoverflow.com/questions/16098903/emailaddressattribute-without-being-required