View Validation With Data Annotations and Custom Client Validations in MVC

In the article Using Data Annotations to validate models I showed that it is possible to maintain validations in attributes.

In this article I will show how to apply these validations on the client side.

By default, when you create a standard MVC project, it creates an entire initial structure for you, including the setup of the scripts. To enable client-side validation you need two keys under appSettings in your web.config file (that are set by default in the standard template):

  1. <add key="ClientValidationEnabled" value="true" />    
  2. <add key="UnobtrusiveJavaScriptEnabled" value="true" />   
You will also need to include both jQuery and jQuery.validate on your pages. By default jQuery is included, but jQuery.validate is not included on _Layout.cshtml, be sure you include it. You also need to put the scripts in order.
  1. @Scripts.Render("~/bundles/jquery")    
  2. @Scripts.Render("~/bundles/jqueryval")    
On the default MVC there are some bundles set up, the code above is using it. You could also manually include the scripts with the script tag.

With the setup ready we can start coding. I will create a model with some data annotations as in the following:
  1. public class Game    
  2. {    
  3.     [Required]    
  4.     [StringLength(5)]    
  5.     public string Name { getset; }    
  6.      
  7.     [Required]    
  8.     [StringLength(5)]    
  9.     public string Genre { getset; }    
  10.      
  11.     [Range(13, 40)]    
  12.     public string Age { getset; }    
  13. }    
And on my view I will create a form with it:
  1. @using (Html.BeginForm())    
  2. {    
  3.     <div>    
  4.         <div>    
  5.             @Html.LabelFor(o => o.Name)    
  6.             @Html.TextBoxFor(o => o.Name)    
  7.             <br />    
  8.             @Html.ValidationMessageFor(o => o.Name)    
  9.         </div>    
  10.         <br />    
  11.         <div>    
  12.             @Html.LabelFor(o => o.Genre)    
  13.             @Html.TextBoxFor(o => o.Genre)    
  14.             <br />    
  15.             @Html.ValidationMessageFor(o => o.Genre)    
  16.         </div>    
  17.         <br />    
  18.         <div>    
  19.             @Html.LabelFor(o => o.Age)    
  20.             @Html.TextBoxFor(o => o.Age)    
  21.             <br />    
  22.             @Html.ValidationMessageFor(o => o.Age)    
  23.         </div>    
  24.      
  25.         <br />    
  26.         <br />    
  27.      
  28.         <input type="submit" value="Submit" />    
  29.     </div>    
  30. }  
The result will be:

result

The object being validated receives the class input-validation-error that can be styled. And the error message receives a field-validation-error that can also be styled. For example, if we want to display a Red border and Red message:
  1. .input-validation-error    
  2. {    
  3.     border: 1px solid red;    
  4. }    
  5. .field-validation-error    
  6. {    
  7.     color: red;    
  8. }    
Custom Client Validation

To make a custom validation and allow it to run on the client side we must create a new attribute that inherits from the ValidationAttribute and implementsIClientValidatable interface. For example:
  1. public class NoSwearWords : ValidationAttribute, IClientValidatable    
  2. {    
  3.     protected override ValidationResult IsValid(object value,    
  4.         ValidationContext validationContext)    
  5.     {    
  6.         string val = value as string ?? "";    
  7.      
  8.         bool valid = !new string[] { "Pus**""F**k" }    
  9.             .Any(o => val.Contains(o));    
  10.      
  11.         if (!valid)    
  12.             return new ValidationResult(    
  13.                 base.FormatErrorMessage(base.ErrorMessage));    
  14.      
  15.         return null;    
  16.     }    
  17.      
  18.     // client-side    
  19.     public IEnumerable<ModelClientValidationRule>    
  20.         GetClientValidationRules(ModelMetadata metadata    
  21.                                , ControllerContext context)    
  22.     {    
  23.         var rule = new ModelClientValidationRule();    
  24.      
  25.         rule.ValidationType = "noswearwords";    
  26.         rule.ErrorMessage = "You cannot use swear words over here";    
  27.      
  28.         yield return rule;    
  29.     }    
  30. }   
I am explaining on the client-side I have a jQuery validator method called “noswearwords” (lowercase name required).

I will decorate the property Comment with it as in the following:
  1. [NoSwearWords]    
  2. public string Comment { getset; }    
To implement this validation on the client side I need to create the method “noswearwords” and register it on the adapters as in the following:
  1. <script type="text/javascript">    
  2.      
  3.     $.validator.addMethod("noswearwords",    
  4.         function (value, element, param) {    
  5.             return !/Pus**|F**k/i.test(value);    
  6.         });    
  7.      
  8.     $.validator.unobtrusive.adapters.add("noswearwords", {},    
  9.         function (options) {    
  10.             options.rules["noswearwords"] = true;    
  11.             options.messages["noswearwords"] = options.message;    
  12.         });    
  13.      
  14. </script>  
Everything else is done automatically for you.

form