Implement a Custom Validation Rule

If the built-in validation rules do not meet your requirements, implement a custom one. These are the steps for you to follow.

  1. In ASP.NET MVC 3, 4, 5, create a class that inherits from the ValidationAttribute and IClientValidatable. In this class, implement the GetClientValidationRules method. Note that this method returns an object of the ModelClientValidationRule type. The ValidationType property of this object should be set to "custom", and the ValidationParameters collection should be given a new entry called "validationCallback", which binds a JavaScript function to the validation rule. This function will be declared in step 3.

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;
    namespace ApplicationName.Models
    {
        public class VerifyAgeAttribute : ValidationAttribute, IClientValidatable
        {
            public VerifyAgeAttribute()
                : base("The value of the {0} field is not valid") {
            }
            public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata,
                ControllerContext context)
            {
                var rule = new ModelClientValidationRule();
                rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
                // Binds the "verifyAge" JavaScript function to the validation rule
                rule.ValidationParameters.Add("validationCallback", "verifyAge");
                // "ValidationType" should always be "custom"
                rule.ValidationType = "custom";
                yield return rule;
            }
        }
    }

    In ASP.NET Core MVC, create a class that inherits from the ValidationAttribute and IClientModelValidator. In this class, implement the following methods.

    • AddValidation
      Adds the custom validation attribute to the collection of validation attributes.

    • MergeAttribute
      Checks that the key of the custom validation attribute is unique within the collection of validation attributes. Note that the key must begin with the "data-val-custom-" prefix. The key that ends with "validationCallback" must point to a JavaScript function implementing the validation logic. This function will be declared in step 3.

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
    namespace ApplicationName.Models
    {
        public class VerifyAgeAttribute : ValidationAttribute, IClientModelValidator
        {
            public VerifyAgeAttribute()
                : base("The value of the {0} field is not valid") {
            }
            public void AddValidation(ClientModelValidationContext context) {
                MergeAttribute(context.Attributes, "data-val-custom-verify-age",
                        FormatErrorMessage(context.ModelMetadata.GetDisplayName()));
                MergeAttribute(context.Attributes, "data-val-custom-verify-age-validationCallback", "verifyAge");
            }
            bool MergeAttribute(IDictionary<string, string> attributes, string key, string value) {
                if(attributes.ContainsKey(key)) {
                    return false;
                }
                attributes.Add(key, value);
                return true;
            }
        }
    }
  2. Attach the custom attribute to a model property.

    using System.ComponentModel.DataAnnotations;
    namespace ApplicationName.Models {
        public class Person {
            // ...
            [VerifyAge(ErrorMessage = "Persons under 21 are not allowed")]
            public int Age { get; set; }
        }
    }
  3. In the view, declare a JavaScript function that implements all validation logic.

    <script>
        function verifyAge (options) {
            if (!(options.value >= 18)) {
                return false;
            }
            return true;
        }
    </script>

To use the custom validation rule, create a DevExtreme editor (in this case, the NumberBox) in the same view where the JavaScript function is declared, and bind this editor to the model property from step 2 using the Name() method.

@model ApplicationName.Models.Person

@(Html.DevExtreme().NumberBox()
    .Name("Age")
    .Value(Model.Age)
)

View Demo

See Also