Allow empty strings for fields marked with PhoneAttribute or UrlAttribute

31,674

Solution 1

Validation attributes like [Phone] and [EmailAddress] will check any non-null string values. Because the string type is inherently nullable, empty strings passed to the ModelBinder are read as null, which passes the validation check.

When you add the [Required] attribute, the string becomes effectively non-nullable. (If using Code First, EF will script a non-nullable database column.) The ModelBinder will now interpret a blank value as String.Empty - which will fail the attribute validation check.

So there is no way to allow empty strings with validation attributes, but you can allow null strings. All you need to do is remove the [Required] attribute. Blank values will be null and non-blank values will be validated.

In my case, I am importing records from a CSV file, and had this problem because I was skipping the normal ModelBinder. If you are doing something unusual like this, be sure to include a manual check before saving to your data model:

Email = (record.Email == String.Empty) ? null : record.Email

Solution 2

Use following two data annotations:

[Required(AllowEmptyStrings = true)]
[DisplayFormat(ConvertEmptyStringToNull = false)]

Solution 3

I did something similar below.

  [JsonProperty("phone")]
  [NullablePhone]
  public string Phone { get; set; }

/// <summary>
/// Validation attribute for phone numbers.
/// </summary>
/// <seealso cref="ValidationAttribute" />
public class NullablePhoneAttribute : ValidationAttribute
{
    /// <summary>
    /// Returns true if phone is empty or valid.
    /// </summary>
    /// <param name="value">The value of the object to validate.</param>
    /// <returns>
    ///   <see langword="true" /> if the specified value is valid; otherwise, <see langword="false" />.
    /// </returns>
    public override bool IsValid(object value)
    {
        if (value == null)
        {
            return true;
        }
        if (string.IsNullOrEmpty(value.ToString()))
        {
            return true;
        }
        PhoneAttribute phone = new PhoneAttribute();
        return phone.IsValid(value);
    }

}
Share:
31,674
Nu-hin
Author by

Nu-hin

Updated on June 25, 2021

Comments

  • Nu-hin
    Nu-hin almost 3 years

    I'm using CodeFirst Entitty framework 5. I have a class representing a user.

    public class User
    {
        [Key]
        public int UserId { get; set; }
    
        [Url]
        [DataType(DataType.Url)]
        [Required(AllowEmptyStrings= true)]
        public string WebSite { get; set; }
    
        [Phone]
        [DataType(DataType.PhoneNumber)]
        [Required(AllowEmptyStrings = true)]
        public string Phone { get; set; }
    
        [Phone]
        [DataType(DataType.PhoneNumber)]
        [Required(AllowEmptyStrings = true)]
        public string Fax { get; set; }
    }
    

    I like the validation mechanics for Phone and Url attributes a lot, but unfortunately validation fails when fields marked with these attributes are empty strings which I actually want to allow. [Required(AllowEmptyStrings = true)] doesn't seem to work with Phone or Url attributes. The same seems to apply to some other DataAnnotations attributes like EmailAddress.

    Is there a way to allow empty strings for fields marked with such attributes?

  • Nu-hin
    Nu-hin over 10 years
    I wasn't using Model Binder. I was writing data importer and the source data contains empty emails and phones. I guess I should just convert empty strings from source to nulls then. Thanks for the explanation!
  • Gerald Davis
    Gerald Davis almost 9 years
    @Nu-hin. Your DBA will thank you in the future if you get in a habbit of cleaning up ambiguous pointless values like empty strings and replacing them with null. Null is undefined or unknown. A empty string phone number is undefined or unknown. Always fun to do work on a db years later and find a mix of null, empty strings, whitespace strings, and the always helpful "NO PHONE NUMBER" in the phone number field.
  • Ian Griffiths
    Ian Griffiths over 8 years
    This seems pretty unhelpful. Yes in some situations, the absence of a value means "not known", but "Definitely empty" means something quite different from "Not known". So there are cases where a empty string is not a "pointless value".
  • daniel.caspers
    daniel.caspers over 7 years
    This did not work for me with the DomainAttribute but did work with the EmailAddressAttribute!
  • Marek Bar
    Marek Bar over 7 years
    Works very well but I wonder why visual has generated in my case [Required][StringLength(10)] if I have not null, nvarchar(10)
  • HGMamaci
    HGMamaci about 7 years
    Removing this "[DisplayFormat(ConvertEmptyStringToNull = false)]" has worked for me. Thank you
  • TheKido
    TheKido about 7 years
    Works for me on Core. Thanks!
  • Mord Zuber
    Mord Zuber over 6 years
    This does not seem to work anymore with System.ComponentModel.DataAnnotations.EmailAddressAttribute as empty strings are failing validation, even though the field is not required
  • Neil Laslett
    Neil Laslett over 6 years
    @MordZuber Interesting. Two options: either EmailAddressAttribute has been updated to validate null strings or the ModelBinder is setting your blank incoming value to string.Empty instead of null. Can you remove the validation and check the actual value set by ModelBinder?
  • Mord Zuber
    Mord Zuber over 6 years
    My case was string.Empty being sent over the wire. Since the validator only checks for null, it was failing, so I just wrote a new wrapper attribute
  • Neil Laslett
    Neil Laslett over 6 years
    EmailAddressAttribute definitely still passes null values. referencesource.microsoft.com/… I wonder why it was setting it to empty?
  • Neil Laslett
    Neil Laslett over 6 years
  • Mário Meyrelles
    Mário Meyrelles almost 3 years
    Indeed. Works on Core API 3.1 also.