Click here to Skip to main content
Click here to Skip to main content

Custom Client Side Validation in ASP.NET MVC3

By , 29 Oct 2011
 

Output Image

Client validation using ASP.NET MVC3 and jQuery

Client Validation

In web applications, users typically expect immediate validation feedback—without having to submit anything to the server. This is known as client-side validation and is usually implemented using JavaScript. The data that the user has entered is validated before being sent to the server, providing the user with immediate feedback and an opportunity to correct any problems.

The MVC Framework supports unobtrusive client-side validation. The term unobtrusive means that validation rules are expressed using attributes added to the HTML elements that we generate. These are interpreted by a JavaScript library that is included as part of the MVC Framework, which uses the attribute values to configure the jQuery Validation library, which does the actual validation work.

ASP.NET MVC supports declarative validation rules defined with attributes from the System.ComponentModel.DataAnnotations namespace. The MVC framework provides extensive support for model validation. The built-in validation attributes is Compare, Range, RegularExpression, Required, StringLength.

How Client-Side Validation Works

<input class="text-box single-line" data-val="true"
data-val-checkage="Age range is 18 to 30 yrs. old."
data-val-checkage-param="29-10-2011" 
data-val-required="The Date of Birth field is required."
id="DateOfBirth" name="DateOfBirth" type="text" value="10-10-2001" />

The MVC client-side validation support doesn't generate any JavaScript or JSON data to direct the validation process; like much of the rest of the MVC Framework, we rely on convention. The first attribute that was added is data-val. The jQuery Validation library identifies those fields that require validation by looking for this attribute.

Individual validation rules are specified using an attribute in the form data-val-, where name is the rule to be applied. So, for example, the Required attribute we applied to the model class has resulted in a data-val-required attribute in the HTML. The value associated with the attribute is the error message associated with the rule. Some rules require additional attributes; you can see this with the checkage rule, which has data-val-checkage-param attribute for current date. We can use current date in jQuery directly, but here we are taking current date as parameter and parameter name is param. to hold current date.

The interpretation of the required and length validation rules is provided by the jQuery Validation library, on which the MVC client validation features are built.

Creating jQuery Client Validation

Output Image

Client validation using jQuery

For creating client validation in jQuery, we require jquery-1.5.1.min.js and jquery.validate.min.js files. Then we create a simple HTML file and client validation JavaScript code file. I have created both fields whose names are mynewrule.htm and checkage.js.

HTML Code (mynewrule.html)

<html>
<head>
<title>Index</title>
<script src="jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="jquery.validate.min.js" type="text/javascript"></script>
<script src="checkage.js" type="text/javascript"></script>
<style type="text/css">
#txtAge,#txtDateOfBirth {width:100;}
</style>
</head>
<body>
<form id="myform">
<label for="txtDateOfBirth">Date of Birth (<b>dd-mm-yyyy</b>): </label>
<input name="txtDateOfBirth" type="text" id="txtDateOfBirth" 
	value="10-04-1980" /><br/><br/>
<input type="submit" value="Submit" id="btnSubmit"  />
Your Current Age:<input name="txtAge" type="text" id="txtAge" value="0" readonly />
</form>
<code><b/></code>
</body>
</html>

js Code (checkage.js)

//Our validation script will go here.
$(document).ready(function () {
    //custom validation rule - checkAge
    $.validator.addMethod("checkAge",
       function (value, element) {
          var currDate=new Date();
          var dobDate = $('#txtDateOfBirth').val();
          var sdob = dobDate.split('-');
		  //pass year,month,date in new Date object.
          var vDOB = new Date(sdob[2], sdob[1], sdob[0]);
		  //getAge user define function to calculate age.
          var vYrs = getAge(vDOB,currDate);
		  var result=false;
		  $('#txtAge').val(vYrs);
		  if(vYrs>=18 && vYrs<=30){
		  result=true; }
          return result;
       });
    //validation implementation will go here.
    $('#myform').validate({
        rules: {
            txtDateOfBirth: {
                required: true,
                checkAge: true,
            }
        },
        messages: {
            txtDateOfBirth: {
                required: "Date of Birth is required.",
				checkAge:"Age range is 18 to 30."
            }
        }
    });
})
//function to calculate age.
function getAge(oldDate,currDate) {
     return currDate.getFullYear() - oldDate.getFullYear();
}

In the above code, the function validate for form validation and create validation rules in this function for input textbox field id is #txtDateofBirth. Here we have some options which are rules, messages and params. Options rules we can define required, range and in our case custom rule checkage. Pass true to apply this rule. Options messages to create different-2 message for different rules and finally option params to pass parameter for rules as per our requirement.

The jQuery.validator object has an API to add new validators. The name of the method is addMethod.
The method takes two parameters: First is the name of the validator, which by convention matches the name of the adapter. Second is a function to invoke when validation occurs.

The validator function accepts three parameters, and can return true (validation passed) or false (validation failed):

  1. The first parameter to the function will contain the input value (like the date of birth textbox value).
  2. The second parameter is the input element containing the value to validate (in case the value itself doesn’t provide enough information).
  3. The third parameter will contain all the validation parameters in an array, or in this case, the single validation parameter (the current date parameter param).

One of the nice features about the MVC client-side validation is that the same attributes we use to specify validation rules are applied at the client and at the server. This means that data from browsers that don't support JavaScript are subject to the same validation as those that do, without requiring us to make any additional efforts.

Create Custom Client-side Validation in ASP.NET MVC 3

Here, we are creating StatusCheckAge to check age must be between 18 to 30.

  1. Create Empty project in Visual Web Developer 2010 Express of MVC3 application.

    Output Image

    Output Image

  2. Right click on Model directory and create class Person.

    public class Person
     {
        [Required,Display(Name="Person Name")]
        public string PersonName { get; set; }
        [StatusCheckAge]
        [Required]
        [Display(Name="Date of Birth")]
        [DisplayFormat(ApplyFormatInEditMode=true,DataFormatString="{0:dd-MM-yyyy}")]
        public DateTime DateOfBirth { get; set; }
     }
  3. Again right click on Model directory and create class StatusCheckAge. For custom validation, you have to derive this class from ValidationAttribute and custom client validation you have to derive this class from IClientValidatable interface. So StatusCheckAge class is derived from both ValidationAttribute,IClientValidatable.
    public class StatusCheckAge : ValidationAttribute,IClientValidatable
    {
        protected override ValidationResult IsValid
    	(object value, ValidationContext validationContext)
        {
            DateTime dtV = (DateTime)value;
            long lTicks = DateTime.Now.Ticks - dtV.Ticks;
            DateTime dtAge = new DateTime(lTicks);
            string sErrorMessage = "Age range is 18 to 30 yrs. old.";
            if (!(dtAge.Year >= 18 && dtAge.Year <= 30)) 
    		{ return new ValidationResult(sErrorMessage); }
            return ValidationResult.Success;
        }
        public IEnumerable<modelclientvalidationrule /> GetClientValidationRules
    	(ModelMetadata metadata, ControllerContext context)
        {
            ModelClientValidationRule mcvrTwo = new ModelClientValidationRule();
            mcvrTwo.ValidationType = "checkage";
            mcvrTwo.ErrorMessage = "Age range is 18 to 30 yrs. old.";
            mcvrTwo.ValidationParameters.Add
    		("param", DateTime.Now.ToString("dd-MM-yyyy"));
            return new List<modelclientvalidationrule /> { mcvrTwo };
        }
    }

    To implement the validation logic, you need to override one of the IsValid methods provided by the base class. Overriding the IsValid version taking a ValidationContext parameter provides more information to use inside the IsValid method (the ValidationContext parameter will give you access to the model type, model object instance, and friendly display name of the property you are validating, among other pieces of information).

    The first parameter to the IsValid method is the value to validate. If the value is valid, you can return a successful validation result, but before you can determine if the value is valid, you’ll need to check value according your validation condition, in our case condition is Age>=18 and Age<=30. And you return a ValidationResult object with a hard-coded error message to indicate a validation error.

    IClientValidatable: The IClientValidatable interface defines a single method: GetClientValidationRules. When the MVC framework finds a validation object with this interface present, it invokes GetClientValidationRules to retrieve — you guessed it — a sequence of ModelClientValidationRule objects. These objects carry the metadata, or the rules, the framework sends to the client.

  4. Now to enable client side validation rule we have to create javascript code file. Here our file name is customclientvalidation.js.

    /// <reference path="jquery-1.5.1.js" />
    /// <reference path="jquery.validate.unobtrusive.js" />
    /// <reference path="jquery.validate.js" />
    
    //custom validation rule - checkAge
    jQuery.validator.addMethod("checkage",
    function (value, element, param) {
        var currDate = param;
        var sdoc = currDate.split('-');
        var dobDate = value;
        var sdob = dobDate.split('-');
        //pass year,month,date in new Date object.
        var vDOB = new Date(sdob[2], sdob[1], sdob[0]);
        var vDOC = new Date(sdoc[2], sdoc[1], sdoc[0]);
        //getAge user define function to calculate age.
        var vYrs = getAge(vDOB, vDOC);
        var result = false;
        if (vYrs >= 18 && vYrs <= 30) { result = true; }
        return result;
    });
    
    jQuery.validator.unobtrusive.adapters.add
    	("checkage", ["param"], function (options) {
    
        options.rules["checkage"] = options.params.param;
        options.messages["checkage"] = options.message;
    });
    
    function getAge(oldDate, currDate) {
        return currDate.getFullYear() - oldDate.getFullYear();
    }

    The MVC framework’s unobtrusive validation extension stores all adapters in the jQuery.validator.unobtrusive.adapters object. Here, we are using add method. parameter is rule name checkage, parameter object array and define function, function takes one argument options to use passing value in rules.

  5. Right click on controller, create Home and write in Create() method of HomeController.
    public class HomeController : Controller
    {
        //
        // GET: /Home/
    
        public ActionResult Index()
        {
            return View(new Person 
    	{ PersonName = "rajendra", DateOfBirth = new DateTime(2001,10,10) });
        }
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Index(Person newPerson)
        {
            if (ModelState.IsValid)
            {
            }
            return View();
        }
    }	
  6. Right click on Create() method of HomeController and add strongly typed view, select scaffold template Create, then ok and add the following references in head tag. ~/Scripts/jquery-1.5.1.min.js,~/Scripts/jquery.validate.min.js, ~/Scripts/jquery.validate.unobtrusive.min.js and ~/Scripts/customclientvalidation.js.

    Output Image

  7. Build and run application.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

R S Dodiya
Web Developer
India India
Member

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 4membersumitkm11 Feb '13 - 16:23 
Neat writeup. What would make it a 5 star is if we could see a way to pass the upper limit and lower limit to the validator. That way the validation would be completely generic.
QuestionproblemmemberMember 161709528 Mar '12 - 7:05 
It seems that server validation does not work properly. It seems that server expects the date format to be MM-dd-yyyy instead of dd-MM-yyyy. Try to validate with 13-02-1987 to see the problem.
AnswerRe: problemmemberMember 161709528 Mar '12 - 7:30 
OK, I found that the problem occurs when the server uses a format different than dd-MM-yyyy. You could use the element in web.config to set the server side culture.
QuestionNice article, but....memberToddHileHoffer13 Jan '12 - 16:46 
Is it really a good idea to put business rules in your view and your model? Doesn't this violate the principle of separation of concerns? What if another developer is maintaining this code five years from now and the validation rules change. Are they going to know that these rules are hard coded in the view (or HTML) as well as the StatusCheckAge class. When MVC is not in vogue and we are doing things in the new and better way, will it be clear to the developer that the attribute [StatusCheckAge] causes the IsValid method to be called. Also, doesn't this seem like an absurd amount of work / code just to do a simple validation? In 1998, this would have been three lines of VB6 code in one file, or a couple of lines of T-SQL in stored procedure. You had to write almost a 50 lines of code in two languages, use custom attributes, class files with the proper base classes etc....

I didn't get any requirements for the signature

GeneralMy vote of 5memberKees Alderliesten7 Nov '11 - 23:15 
Nice! Thanks!
GeneralMy vote of 5memberMember 41481882 Nov '11 - 7:53 
Excellent article. Will give client validation a try in my next project.
 
Keep up the good work!!
GeneralMy vote of 2memberMohammad_Denmark1 Nov '11 - 6:17 
difficult and rather lengthy.
GeneralRe: My vote of 2memberKees Alderliesten7 Nov '11 - 23:15 
Are you serious???
GeneralRe: My vote of 2memberToddHileHoffer13 Jan '12 - 16:58 
He does have a point. There is a high degree of work / difficulty for such a trivial task. Who has time to make multiple files / 50 lines of code to determine is (currentDate.Year - dateOfBirth.Year between 18 & 30)? Seriously, could make something so easy any more difficult?

I didn't get any requirements for the signature

GeneralRe: My vote of 2membersumitkm11 Feb '13 - 16:21 
The fact that custom validators are difficult to write is not the author's fault, that's how the framework needs it to be.
The Author as done a good job of explaining the requirements, the use-case selected may be trivial. Ranting about the number of lines of code required is out of place!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 29 Oct 2011
Article Copyright 2011 by R S Dodiya
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid