8

I am working on a form registration for ApplicationUser. There, I have a field Email or phone like Facebook. I am using DataAnnotation for model validation. In Data annotation I get [EmailAddress] for email validation and [Phone] for phone number validation. But I need something like [EmailAddressOrPhone]. So how I can achieve that?

public class RegisterViewModel
{
    .....

    [Required]
    [Display(Name = "Email or Phone")]
    public string EmailOrPhone { get; set; }

    ......
}
Laurel
  • 5,965
  • 14
  • 31
  • 57
Zubayer Bin Ayub
  • 310
  • 3
  • 11

3 Answers3

6

You shouldn't use your own regex to validate email addresses, however I personally would be using the following logic to determine if it is a valid email address. If it isn't a valid email address, you can assume it's a phone number.

The following code uses the [EmailAddress] attribute that you've already mentioned, but within the code. This way you don't have to invent your own way of validating the email address.

public EmailOrPhoneAttribute : ValidationAttribute
{
    public override IsValid(object value)
    {
        var emailOrPhone = value as string;

        // Is this a valid email address?
        if (this.IsValidEmailAddress(emailOrPhone))
        {
           // Is valid email address
           return true;
        }
        else if (this.IsValidPhoneNumber(emailOrPhone))
        {
            // Assume phone number
            return true;
        }

        // Not valid email address or phone
        return false;
    }

    private bool IsValidEmailAddress(string emailToValidate)
    {
        // Get instance of MVC email validation attribute
        var emailAttribute = new EmailAddressAttribute();

        return emailAttribute.IsValid(emailOrPhone);
    }

    private bool IsValidPhoneNumber(string phoneNumberToValidate)
    {
        // Regualr expression from https://stackoverflow.com/a/8909045/894792 for phone numbers
        var regex = new Regex("^\+?(\d[\d-. ]+)?(\([\d-. ]+\))?[\d-. ]+\d$");
        return regex.IsMatch(phoneNumberToValidate)
    }
}

Naturally you will need to determine how you are going to determine if the phone number is correct yourself, because phone numbers are different in different countries. I've just taken a regular expression from this question as an example.

Community
  • 1
  • 1
Luke
  • 22,826
  • 31
  • 110
  • 193
  • I guess you meant `new Regex(@"^\+?(\d[\d-. ]+)?(\([\d-. ]+\))?[\d-. ]+\d$")` – Wiktor Stribiżew Oct 01 '16 at 18:57
  • but `[EmailAddress]` attribute also use `regex` under the hood and for email validation `regex` [http://emailregex.com] says it works for 99.99% case. – Mahbubur Rahman Oct 02 '16 at 01:18
  • 1
    Yes, but you don't have to maintain it, it's part of the framework. – Luke Oct 02 '16 at 09:48
  • 2
    You can also use `PhoneAttribute` instead of `Regex` for phone validation see [microsoft doc](https://learn.microsoft.com/en-gb/dotnet/api/system.componentmodel.dataannotations.phoneattribute?view=netcore-2.2) – Mojtaba Jul 18 '19 at 16:50
4

You can achieve this using Regex. You have to combine the regex for email and phone together.

public class RegisterViewModel
{
    [Required]
    [Display(Name = "Email or Phone")]
    /* /<email-pattern>|<phone-pattern>/ */
    [RegularExpression(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$|^\+?\d{0,2}\-?\d{4,5}\-?\d{5,6}", ErrorMessage = "Please enter a valid email address or phone number")]      
    public string EmailOrPhone { get; set; }
}

Or You can create a custom attribute

 public class EmailOrPhoneAttribute : RegularExpressionAttribute
 {
    public EmailOrPhoneAttribute()
        : base(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$|^\+?\d{0,2}\-?\d{4,5}\-?\d{5,6}")
    {
        ErrorMessage = "Please provide a valid email address or phone number";
    }
 }

and use that

 public class RegisterViewModel
 {
    [Required]
    [Display(Name = "Email or Phone")]
    [EmailOrPhone]    
    public string EmailOrPhone { get; set; }
 }
Mahbubur Rahman
  • 4,961
  • 2
  • 39
  • 46
  • It works fine unless I want to sign up to your website with a perfectly valid email address like `BŌb@bob.com`. Then it doesn't work. – Luke Oct 02 '16 at 09:56
  • yes. you are right. In that case updating the `Regex` will solve the issue. Any one can use the regex that `System.ComponentModel.DataAnnotations` uses from the [source](https://github.com/Microsoft/referencesource/blob/master/System.ComponentModel.DataAnnotations/DataAnnotations/EmailAddressAttribute.cs) . I just wanted to meant `shouldn't use a regex to validate email addressess` sounds creepy. – Mahbubur Rahman Oct 02 '16 at 11:12
  • Creepy? It's not creepy, what it means is use the framework that has been provided to you. Why would you write and maintain your own Regex code when it is provided and maintained as part of the framework? [The docs recommend using the `MailAddress` class](https://msdn.microsoft.com/en-us/library/01escwtf.aspx) – Luke Oct 02 '16 at 12:49
2

In addition to custom attributes, you can have a look to this library: https://github.com/jwaliszko/ExpressiveAnnotations

An example is:

[Required]
[AssertThat("IsEmail(EmailOrPhone) || (Length(EmailOrPhone) > 8 && Length(EmailOrPhone) < 16 && IsRegexMatch(EmailOrPhone, '^\\d+$'))",
    ErrorMessageResourceType = typeof (Resources), ErrorMessageResourceName = nameof(Resources.EmailFormatInvalid))]
[Display(Name = "EmailOrPhone")]
public string EmailOrPhone { get; set; }

where I have used AssertThat attribute from ExpressiveAnnotations and created a error message EmailFormatInvalid in a Resources file.

peval27
  • 1,239
  • 2
  • 14
  • 40
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/13856254) – zinking Oct 02 '16 at 09:25
  • I have updated the answer to include code. Sorry about that, I'm a newbie in SO answers – peval27 Oct 02 '16 at 15:07
  • 1
    I was struggling with proper use of IsRegexMatch - thank you! – Beamer Nov 26 '21 at 04:25