softshipper
softshipper

Reputation: 34081

Validate before adding to collection

I have following class inherent from ObservableCollection:

public class Emails : ObservableCollection<Email>
    {
        public Emails()
        {
        }

        public Emails(IEnumerable<Email> emails)
        {
            foreach (var e in emails)
            {
                //   Will throw System.FormatException:
                //     address is not in a recognized format.
                var addr = new System.Net.Mail.MailAddress(e.Address);
                Add(e);
            }
        }

        public IEnumerable<Email> GetAll()
        {
            return Items;
        }

    }

My question is, before an element will be added, how can I validate the item? I will validate, if the mail is in the right format.

Upvotes: 0

Views: 164

Answers (4)

ivamax9
ivamax9

Reputation: 2629

What about to do it like there. And then use it in your constructor:

public class Emails : ObservableCollection<Email>
{
   public Emails()
   {
   }

   public Emails(IEnumerable<Email> emails)
   {
      foreach (var e in emails)
      {
        if(IsValidEmail(e.Address)
        {
          Add(e);
        }
      }
   }

  public IEnumerable<Email> GetAll()
  {
     return Items;
  }    
}

Upvotes: 0

amiry jd
amiry jd

Reputation: 27585

You should create a new version of Add, SetItem, and InsertItem:

public class Emails : ObservableCollection<Email> {
    public Emails() {
    }

    public Emails(IEnumerable<Email> emails) {
        foreach (var e in emails) {
            Add(e);
        }
    }

    public IEnumerable<Email> GetAll() {
        return Items;
    }

    protected bool InsertItem(int index, Email item, bool throwOnInvalidEmailAddress = false) {
        if (IsValidEmailAddress(item.Address)) {
            base.InsertItem(index, item);
            return true;
        }
        if (throwOnInvalidEmailAddress)
            throw new Exception("Bad email address!");
        return false;
    }

    protected bool SetItem(int index, Email item, bool throwOnInvalidEmailAddress = false) {
        if (IsValidEmailAddress(item.Address)) {
            base.SetItem(index, item);
            return true;
        }
        if (throwOnInvalidEmailAddress)
            throw new Exception("Bad email address!");
        return false;
    }

    public bool Add(Email item, bool throwOnInvalidEmailAddress = false) {
        if (IsValidEmailAddress(item.Address)) {
            base.Add(item);
            return true;
        }
        if (throwOnInvalidEmailAddress)
            throw new Exception("Bad email address!");
        return false;
    }

    private static readonly Regex EmailValidatorRegex = 
        new Regex(@"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$");
    private bool IsValidEmailAddress(string address) {
        return !string.IsNullOrWhiteSpace(address) && EmailValidatorRegex.IsMatch(address);
    }
}

Note 1: The used Regex came from @LInsoDeTeh 's answer

Note 2: You can use the provided throwOnInvalidEmailAddress parameter, to decide what to do with invalid addresses e.g. ignore them, throw an exception, ...

Upvotes: 0

Thorsten Dittmar
Thorsten Dittmar

Reputation: 56697

There are many threads here and on other forums about the problems with email validation. The general consensus is: don't. Especially don't use regular expressions to do it.

One valid way is to send an eMail to the address and check whether that succeeds.

On the other hand your code comments already give a hint about an exception being thrown. If you change the code as follows, you can only add valid addresses:

public Emails(IEnumerable<Email> emails)
{
        List<Email> invalid = new List<Email>();

        foreach (var e in emails)
        {
            //   Will throw System.FormatException:
            //     address is not in a recognized format.
            try
            {
                var addr = new System.Net.Mail.MailAddress(e.Address);
                Add(e);
            }
            catch (FormatException)
            {
                // The address was invalid. Add to a list of invalid
                // addresses
                invalid.Add(e);
            }
        }
}

This generates a list of invalid addresses and adds the valid addresses to your collection.

Upvotes: 2

LInsoDeTeh
LInsoDeTeh

Reputation: 1038

You can check with a regex:

Regex emailRegex = new Regex(@"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$");
if (emailRegex.IsMatch(e.Address) {
     //valid eMail address
}

Upvotes: 0

Related Questions