Search code examples
c#asp.net-mvcclient-side-validationvalidationattribute

Custom email address attribute on client side


Evening all!

I've created the below validation attribute to check a list of emails are valid.

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class EmailAddressListAttribute : ValidationAttribute, IClientValidatable
{
    private const string RegexPattern = @"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*" +
                                        @"@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        ErrorMessage = $"{validationContext.DisplayName} contains invalid email addresses";

        var emailList = value.ToString().Split(';');
        return emailList.Where(e => !IsValidEmail(e))
            .ToList()
            .Count == 0 ? null : new ValidationResult(ErrorMessage);
    }

    private static bool IsValidEmail(string emailAddress)
    {
        return Regex.IsMatch(emailAddress, RegexPattern, RegexOptions.IgnoreCase);
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = ErrorMessage,
            ValidationType = "emailaddresslist"
        };
    }
}

I want to be able to utilize this on the client side but I'm unsure how I go about doing this. Any suggestions would be greatly appreciated.

Cheers,

Z

EDIT

I've added the below JS code as a file and I'm rendering it on my view. It's running on page load but doesn't seem to do anything when submit the form.

(function ($) {
$.validator.unobtrusive.adapters.addSingleVal("emailaddresslist");

$.validator.addMethod("emailaddresslist", function (value, element, params) {
    return false;
});
}(jQuery));

Solution

  • I got it working! Here's the code for my attribute

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public sealed class EmailAddressListAttribute : ValidationAttribute, IClientValidatable
    {
        private const string DefaultErrorMessage = "{0} contains invalid email addresses.";
        private const string RegexPattern = @"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*" +
                                            @"@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
    
        public EmailAddressListAttribute()
          : base(DefaultErrorMessage)
        {
        }
    
        public override string FormatErrorMessage(string name)
        {
            return string.Format(ErrorMessageString, name);
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            ErrorMessage = $"{validationContext.DisplayName} contains invalid email addresses";
    
            if (value.ToString().IsNullOrWhiteSpace()) return null;
    
            var emailList = value.ToString().Split(';');
    
            return emailList.Where(e => !IsValidEmail(e))
                .ToList()
                .Count == 0 ? null : new ValidationResult(ErrorMessage);
        }
    
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var clientValidationRule = new ModelClientValidationRule()
            {
                ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                ValidationType = "emailaddresslist"
            };
    
            clientValidationRule.ValidationParameters.Add("otherproperty", "");
    
            return new[] { clientValidationRule };
        }
    
        private static bool IsValidEmail(string emailAddress)
        {
            return Regex.IsMatch(emailAddress, RegexPattern, RegexOptions.IgnoreCase);
        }
    }
    

    And here's the jquery that does the client side.

    (function ($) {
    $.validator.addMethod("emailaddresslist", function (value, element, params) {
        if (!this.optional(element)) {
            if (value == "") return true;
            var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            var emailAddressList = value.split(";")
            var arrayLength = emailAddressList.length;
            for (var i = 0; i < arrayLength; i++) {
                if (!re.test(emailAddressList[i].trim())) return false;
            }
        }
        return true;
    });
    $.validator.unobtrusive.adapters.addSingleVal("emailaddresslist", "otherproperty");
    }(jQuery));