title: Server Side Custom Data Annotation Validation MVC 3
body: <p>I have been trying to make an EmailAddress custom data annotation attribute properly validate emails, and it doesn't seem to be working for me in my tests.</p>
  
  <p>Here's the test:</p>
  
  <pre><code>    [Test]
      public void ModelStateValidation()
      {
          var invalidEmails = new[] { "testtestcom", "test@testcom", "testtest.com" };
          var validEmail = "test@test.com";
  
          //Invalid Email addresses 
          foreach (var invalidEmail in invalidEmails)
          {
              var subscription = new SubscriberModel() { FirstName = "f", LastName = "l", Email = invalidEmail, ConfirmEmail = invalidEmail, DateSubscribed = DateTime.Now };
              ValidateModelAsFalse(subscription);
          }
  
          var subscription2 = new SubscriberModel() { FirstName = "f", LastName = "l", Email = "t", ConfirmEmail = "t", DateSubscribed = DateTime.Now };
          ValidateModelAsFalse(subscription2);
  
          //Valid Email address
          var subscription3 = new SubscriberModel() { FirstName = "f", LastName = "l", Email = validEmail, ConfirmEmail = validEmail, DateSubscribed = DateTime.Now };
          ValidateModelAsTrue(subscription3);
  
          //Last Name doesn't exists
          var subscription4 = new SubscriberModel() { FirstName = "f", LastName = "", Email = validEmail, ConfirmEmail = validEmail, DateSubscribed = DateTime.Now };
          ValidateModelAsFalse(subscription4);
  
          //First Name doesn't exists
          var subscription5 = new SubscriberModel() { FirstName = "", LastName = "l", Email = validEmail, ConfirmEmail = validEmail, DateSubscribed = DateTime.Now };
          ValidateModelAsFalse(subscription5);
  
          //Email addresses are equal
          var subscription6 = new SubscriberModel() { FirstName = "f", LastName = "l", Email = "test@test.com", ConfirmEmail = "test2@test.com", DateSubscribed = DateTime.Now };
          ValidateModelAsFalse(subscription6);
      }
  
      private static void ValidateModelAsFalse(SubscriberModel subscription3)
      {
          SubscriptionController controller = new SubscriptionController();
          controller.ValidateModel(subscription3);
          AssertIsFalse(controller);
      }
  
      private static void ValidateModelAsTrue(SubscriberModel subscription3)
      {
          SubscriptionController controller = new SubscriptionController();
          controller.ValidateModel(subscription3);
          AssertIsTrue(controller);
      }
  
      private static void AssertIsTrue(SubscriptionController controller)
      {
          Assert.That(controller.ModelState.IsValid, Is.True);
      }
  
      private static void AssertIsFalse(SubscriptionController controller)
      {
          Assert.That(controller.ModelState.IsValid, Is.False);
      }
  </code></pre>
  
  <p>Here's the ValidateModel method:</p>
  
  <pre><code>&lt;!-- language: c# --&gt;
  public static void ValidateModel&lt;T&gt;(this Controller controller, T model)
      {
          var validationContext = new ValidationContext(model, null, null);
          var validationResults = new List&lt;ValidationResult&gt;();
          Validator.TryValidateObject(model, validationContext, validationResults);
          foreach (var validationResult in validationResults)
          {
              controller.ModelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage);
          }
      }
  </code></pre>
  
  <p>Model:</p>
  
  <pre><code>&lt;!-- language: c# --&gt;
  public partial class SubscriberModel
  {
      public int SubscriberID { get; set; }
  
      [Required]
      [DisplayName("First Name")]
      public string FirstName { get; set; }
  
      [Required]
      [DisplayName("Last Name")]
      public string LastName { get; set; }
  
      [Required]
      [EmailAddress]
      [Compare("ConfirmEmail", ErrorMessage = "The emails must match")]
      [DisplayName("E-mail")]
      public string Email { get; set; }
  
      [Required]
      [DisplayName("Confirm E-mail")]
      public string ConfirmEmail { get; set; }
  
      [Required]
      [DisplayName("Date Subscribed")]
      public DateTime DateSubscribed { get; set; }
  }
  </code></pre>
  
  <p>Controller:</p>
  
  <pre><code>    public partial class SubscriptionController : Controller
  {
      public ActionResult Index()
      {
          return View();
      }
  
      [CaptchaValidator]
      [HttpPost]
      public ActionResult Index(SubscriberModel subscription, bool captchaValid)
      {
          subscription.DateSubscribed = DateTime.Now;
          ModelStateValid = ModelState.IsValid;
  
          if(captchaValid)
          {
              if (ModelState.IsValid)
              {
                  var test = "";
              }
          }
  
          return View(subscription);
      }
  }
  </code></pre>
  
  <p>EmailAttribute class:</p>
  
  <pre><code>[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
  public sealed class EmailAddressAttribute : ValidationAttribute, IClientValidatable
  { 
      private static Regex _regex = new Regex(@"^((([a-z]|\d|[!#\$%&amp;'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&amp;'\*\+\-\/=\?\^_`{\|}~]|[\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.IgnoreCase);
  
      public EmailAddressAttribute()
          : base()
      {
          ErrorMessage = "Invalid Email";
      }
  
      public IEnumerable&lt;ModelClientValidationRule&gt; GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
          yield return new ModelClientValidationRule {
              ValidationType = "email",
              ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
          };
      }
  
      public override bool IsValid(object value) 
      {
          if (value == null) {
              return false;
          }
  
          string valueAsString = value as string;
          return _regex.Match(valueAsString).Success;
      }
  }
  </code></pre>
  
  <p>The IsValid method seems to validate email addresses as I intend, but for some reason when I go to run the unit test on the Controller.ValidateModel, it doesn't return false and match my Assertion.</p>