ASP.NET MVC made the model validations very easy by using data annotations and unobtrusive validations. Sometimes I run into situations where I have to do custom client side validation. Using ASP.NET MVC framework’s custom validation attributes is a tedious approach and needs lot of coding. In order to do these kinds of custom JavaScript validations, I built a generic JavaScript validation attribute which makes client side validations seamless and fits in the same design principles as that of other model validators. In this blog I go through the implementation of this custom JavaScript validator.

Advantages:

Some obvious advantages are:

  1. User needs to call only one attribute with any custom name (JavaScript function name) for any number of fields. The custom name should be different forfields (for email and date, JavaScript functions would be different). However if two fields require same validation (like for First Name and Last Name), then thecustom function can be same.
  2. The user does not need to follow a set of validation rules set by jQuery.Validator. User has more freedom over the JavaScriptcode following a lesser set of instructions.
  3. It uses fewer lines of code for setting up a custom validator as only one core JavaScript method “jsinvoker” is there for allfields.
  4. It is easier to use. User just needs to include the library and write his/her own JavaScript validation code (definition of functions) and invoke themusing the library and custom attribute class.

Solution:

Our aim is to validate a form having varied fields (like names, email, dates, password, pan etc.) using custom Attribute and JavaScript in ASP.NET MVC 4 application. Here custom attribute is user defined attribute class extending a base class “ValidationAttribute” and an interface “IClientValidatable” (added since MVC3). It takes a JavaScript function name as one of the inputs and calls JavaScript code/ function (with the same name as passed from attribute as input parameter) to validate the field and generates an error if field does not meet certain criteria set by the user. The definition of the JavaScript can be present at either in view or some JavaScript file.

Implementation:

Step 1: Creating Custom Attribute

a. Create a custom attribute class like “JavaScriptCustomValidatorAttribute”

b. Extend this using the base class “ValidationAttribute” and an interface “IClientValidatable”

/// <summary>
/// Custom attribute class
/// </summary>
public class JavaScriptCustomValidatorAttribute: ValidationAttribute, IClientValidatable
{}

c. Create constructors as per use (depending on the number of parameters needed to be passed from the attribute)

/// <summary>
/// CustomValidator class constructors
/// </summary>
/// <param name=”Custom”></param>
public JavaScriptCustomValidatorAttribute(string functionName)
{
      fName = functionName;
}

public JavaScriptCustomValidatorAttribute(string functionName, string[] collection)

{
      fName = functionName;
      this.fCollection = collection;
}

      d. Override the virtual methods of class “ValidationAttribute

/// <summary>
/// Checks for the validity of the value entered
/// </summary>
/// <param name=”value”></param>
/// <returns></returns>
public override bool IsValid(object value)
{
       return true;
}

/// <summary>
/// Formats the error message
/// </summary>
/// <param name=”name”></param>
/// <returns></returns>
public override string FormatErrorMessage(string name)
{
       return String.Format(ErrorMessageString, name);
}

e. Implement the method “GetClientValidationRules” of the interface

/// <summary>
/// Gets the javascript method name and error message and return to jquery adapter
/// </summary>
/// <param name=”metadata”></param>
/// <param name=”context”></param>
/// <returns></returns>
public IEnumerable<ModelClientValidationRule>

GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
       var rule = new ModelClientValidationRule
      {
            ErrorMessage =             FormatErrorMessage(metadata.DisplayName),             ValidationType = “jsinvoker”
      };

// if other parameters are also passed alongwith the function name
if (!(null == fCollection))
{
      rule.ValidationParameters[“properties”] =       string.Join(“,”,fName)+ “,” + 
      string
.Join(“,”, fCollection);

}
// only function name is passed
else
{
      rule.ValidationParameters[“properties”] =       string.Join(“,”, fName);
}
yield return rule;

}

In the “rule” variable, there are two properties set. One is “ErrorMessage” which takes the error message to be shown and second “ValidationType” which takes the JavaScript method name present in the JavaScript library which actually invokes the JavaScript validation methods.

“rule.ValidationParameters[]” dictionary are used to pass parameters to the JavaScript function. Through this, we are passing the validation function names and/ or other parameters if needed.

Step 2: Creating JavaScript library

         $(function () {
                if ($.validator) {

            // adds an javascript invoker function
            $.validator.addMethod(‘jsinvoker’,
            function
(value, element, params) {
            var paraListArray = ”;
            var fname = ”;
            var parameterList = params.properties;
            if (parameterList) {
            paraListArray = parameterList.split(‘,’);
            fname = paraListArray[0];
            // calling the js function with the same name as              passed from attribute
             return window[fname](value, element,
            params);
            }
            else {
             return false;
            }
            },”);

            //adding adapter
            $.validator.unobtrusive.adapters.add(
           ‘jsinvoker’,[‘properties’], function(options){
               options.rules[‘jsinvoker’] = options.params;
               options.messages[‘jsinvoker’] = options.message;
            });
});

  • Create a validator adapter using “$.validator.unobtrusive.adapters.add” with the same name as passed from custom attribute(here it is “jsinvoke”).
  • Set the “option.rules” and “option.messages“ with the required values as shown in the code
  • Then add a method using “$.validator.addMethod” with the same name as passed from custom attribute. From this, we have thename of the function passed, value of the field to be validated and field’s object.
  • Then we call the JavaScript function with the same name as passed from attribute (here it is paraListArray[0]) using “window[paraListArray[0]](value, element, params);”. The parameters we are getting as comma separated list. So we need to split it into an array.

Step 3: Creating JavaScript validation methods in the View or any .js file.

      a. Create functions with the same names as names passed from Attributes defined for each field

      b. Each method should return a bool value to the library method (here it is “jsinvoker”)

[JavaScriptCustomValidator(“validateFirstName“, ErrorMessage =”The first name is invalid“)]

public string FirstName { get; set; }

[JavaScriptCustomValidator(“validateLastName“, ErrorMessage =”The last name is invalid“)]

public string LastName { get; set; }

The above code lines depict the usage of a custom attribute. “JavaScriptCustomValidator” is a custom attribute. “validateFirstName” is the name of the custom JavaScript function name which can be anything defined the user. “ErrorMessage” takes the error message to be shown.

// validates first name
function validateFirstName(value, element, param) {
       var namePattern = /^[a-zA-Z]+$/;
       return namePattern.test(value);
}

The above code is the JavaScript validation function “validateFirstName”. This is called by the “jsinvoker” function and it returns bool. In this method user has all the required objects/ parameters/ values needed to validate the field. Any custom code can be written in these functions to validate the fields.

 

Code Usage:

Step 1: Create a model property in the sample MVC4 application

            public string FirstName { get; set;}

Step 2: Create a field in view with name in model as “FirstName” and your own display name

@Html.LabelFor(m => m.FirstName, “First Name“)
@Html.TextBoxFor(m => m.FirstName)
@Html.ValidationMessageFor(m => m.FirstName)

Note: “ValidationMessageFor” is for showing the error message for that field

Step 3: Create an attribute (like “JavaScriptCustomValidator”). The “ValidationType” property should have the value “jsinvoker”

 

Step 4: Write the attribute at the top of the model as this with the function name and error message:

[JavaScriptCustomValidator(“validateFirstName“, ErrorMessage =”The first name is invalid“)]

public string FirstName { get; set; }

Step 5: Write the required JavaScript functions either in the concerned view or any .js file with the same names as passed from Attribute

 

References:

http://msdn.microsoft.com/en-us/vs2010trainingcourse_aspnetmvccustomvalidation.aspx

http://www.codeproject.com/Articles/301022/Creating-Custom-Validation-Attribute-in-MVC-3

http://forums.asp.net/t/1700735.aspx/1

http://docs.jquery.com/Plugins/Validation/Validator/addMethod

http://thepursuitofalife.com/asp-net-mvc-3-unobtrusive-javascript-validation-with-custom-validators/

http://johnmj.wordpress.com/2011/02/25/unobtrusive-custom-validator-for-mvc3/

http://stackoverflow.com/questions/5662923/asp-net-mvc3-custom-validation-attribute-client-side-broken

http://stackoverflow.com/questions/4747184/perform-client-side-validation-for-custom-attribute

http://stackoverflow.com/questions/5154231/how-does-dataannotations-really-work-in-mvc