User987
User987

Reputation: 3823

Custom data annotation validation attribute with client side validation

I have made a custom data annotation attribute which verifies whether an email already exists in my database like this:

   public class ValidateEmail : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            using (var ctx = new myCtx())
            {
                if (value != null)
                {
                    var valueAsString = value.ToString().ToLower();
                    IEnumerable<string> email = ctx.Users.Where(x => x.Email != null).Select(x => x.Email);
                    if (email.Contains(valueAsString))
                    {
                        var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                        return new ValidationResult(errorMessage);
                    }
                }
                return ValidationResult.Success;
            }
        }
    }

And in my view model I set it like this:

   [ValidateEmail(ErrorMessage = "Email exists")]
        [Required(ErrorMessage = "Required")]
        [RegularExpression(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$", ErrorMessage = "Invalid Email")]
        public string Email { get; set; }

This works perfectly when the page reloads...But I would like now to change this so that I enable client side validation and message displaying without reloading the page itself...

How can I modify this validation attribute to make it compliable with jquery's unobstrusive validation in .NET MVC?

Based on @Sayan's link, I've implemented something like this:

   public class ValidateEmail : ValidationAttribute, IClientValidatable
    {
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationType = "emailvalidate";

            yield return rule;

        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            using (var ctx = new myContext())
            {
                if (value != null)
                {
                    var valueAsString = value.ToString().ToLower();
                    IEnumerable<string> email = ctx.Users.Where(x => x.Email != null).Select(x => x.Email);
                    if (email.Contains(valueAsString))
                    {
                        var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                        return new ValidationResult(errorMessage);
                    }
                }
                return ValidationResult.Success;
            }
        }
    }

and client side:

$.validator.addMethod("emailvalidate", function (value, element) {
{
    console.log("value: " + value + " " + element);
}});
$.validator.unobtrusive.adapters.add("emailvalidate", function (options) {

      //adding rules for validator
    options.rules["emailvalidate"] = true;
    if (options.message) {
        options.messages["emailvalidate"] = options.message;
    }

});

But whatever I insert now in the email field as email like:

[email protected] 

I get the error that email exists ?

Upvotes: 1

Views: 1662

Answers (1)

Sayan Pal
Sayan Pal

Reputation: 4946

You can implement IClientValidatable in your ValidateEmail validation attribute to supply the data-val-xxx attributes to the client side.

Then you can write the jQuery unobtrusive validator and adapter to validate the field value on client side using the data-val-xxx rendered in HTML.

Make sure to return true (truthy value) or false (falsy value) from the jQuery validator based on whether the field value is valid or not respectively.

Lastly, include this custom jQuery validator script to your view.

You can find more details here. Though this blog post presents a slightly complicated scenario, but seeing how to use IClientValidatable and how to write jQuery unobtrusive validator is enough.

Hope this is helpful.

Upvotes: 1

Related Questions