Click here to Skip to main content
Click here to Skip to main content
Go to top

Creating Client and Server-Side Form Validation using the Validator Toolkit for ASP.NET MVC

, 12 Feb 2008
Rate this:
Please Sign up or sign in to vote.
This article describes how to validate an HTML form on client and server-side in conjunction with the jQuery JavaScript library.

Introduction

Microsoft just released the first preview of ASP.NET MVC Framework and it's Microsoft's way to develop Web applications based on the model-view-controller architecture. It will not replace the classic ASP.NET WebForms model. For more information about the new Framework, please see the Scott Guthrie's blog message.

Since there is just a first preview version available, the final feature list is not complete. At this point of time, there is no built-in solution to validate an HTML form on the client and server-side using a standardized system. The Validator Toolkit for ASP.NET MVC offers a way to do form validation on the client and server-side using validation sets. The toolkit is a new project on Microsoft's Open Source Community site at CodePlex.com.

NOTICE: The latest version of the source code and the sample site for the Validator Toolkit can be downloaded from the CodePlex project (source code tab).

The screenshots below give you an idea about how the toolkit will work:

Screenshot1.jpg

Screenshot2.jpg

Here's another screenshot showing how the error messages can be displayed:

Screenshot3.jpg

Now, let's start!

Solution

As mentioned above, the toolkit uses validation sets as a crucial element. Validation sets are special classes that derive from the ValidationSet base class and define all validation rules (validators) for an HTML form. The toolkit generates client-side JavaScript code based on the defined validators during the view rendering.

The client-side uses the very powerful jQuery JavaScript library in conjunction with the jQuery validation plug-in to fulfil the final task of client validation. For more information regarding jQuery and the plug-in, please take a look at the following links:

The validation plug-in used by the toolkit is slightly customized to support all the needed behaviour. Besides using the jQuery library for client validation, you can use it for a lot of other stuff, like animations or DOM manipulation. There are also a lot of plug-ins developed that extend the core library. Validation sets are also used to validate forms on the server (based on the Request.Form collection).

Before we go ahead, let's have a look at a sample validation set:

public class LoginValidationSet : ValidationSet {

   protected override ValidatorCollection GetValidators() {
   
      return new ValidatorCollection (
         new ValidateElement("username") 
            { Required = true, MinLength = 5, MaxLength = 30 },
         new ValidateElement("password") 
            { Required = true, MinLength = 3, MaxLength = 50 }
      );
   }
} 

This LoginValidationSet class defines the rules for validating a simple login form by overriding the GetValidators method of the base class. The method must return a ValidatorCollection instance with all validators used to validate the HTML form later on. In this case, the username field is required and the input for it must contain at least 5 characters and a maximum of 30 characters. The password field is required too, but within the boundaries of 3 and 50 characters.

The order of the defined validators also defines the execution order of validation process. If the toolkit would use custom attributes to set validation rules instead of the method GetValidators, there is no guarantee for the validation process to validate in the same order the attributes are defined, since the Type.GetCustomAttributes method returns the attribute list in alphabetical order.

Of course, you can also write your own custom validators or you may use the ValidateScriptMethod validator which allows you to call a specific JavaScript function on the client-side and a method within the validation set class for the server-side. More on that later.

Once a validation set class is defined, you attach it to the view and the HTML form processing controller action using the ValidationSet attribute, like this:

//
// File: LoginController.cs
//
public class LoginController : Controller {

   [ControllerAction]
   public void Login() {
      RenderView("Login");
   }

   [ControllerAction]
   [ValidationSet(typeof(LoginValidationSet))]
   public void Authenticate() {
      if(this.ValidateForm())
         RenderView("Overview");
      else
         RenderView("Login");
   }
}   

...

//
// File: Login.aspx.cs (CodeBehind)
//
[ValidationSet(typeof(LoginValidationSet))]
public partial class Login : ViewPage {

   [ValidationSet(typeof(LoginValidationSet))]
   public partial class Login : ViewPage {
   }
}

The controller action Authenticate then calls the ValidateForm method, which uses the ValidationSet attribute to do the server-side form validation, based on the NameValueCollection Request:Form.

Within the HTML page, you need to initialize script validation for the login form (loginForm) as follows:

<script type="text/javascript">
   $(function(){
     updateSettingsForSample1ValidationSet($('#loginForm').validate({rules:{}}));
   });
</script>

In the next step, you define the HTML form as usual:

<form id="loginForm" action="/Login/Authenticate" method="post">
   Username: <input type="text" id="username" name="username" /><br />
   Password: <input type="text" id="password" name="password" /><br />
   <input type="submit" value="Login" />
</form> 

Finally, the script that defines the validation rules must be defined:

<% this.RenderValidationSetScripts(); %>

You also need to include the jQuery JavaScript library into the form or master page. See the Validator Toolkit sample site for more information. Sample site of the toolkit includes the scripts in the master page:

<script type="text/javascript" src="../../Content/jDate.js"></script>
<script type="text/javascript" src="../../Content/jQuery.Core.js"></script>
<script type="text/javascript" src="../../Content/jQuery.Delegate.js"></script>
<script type="text/javascript" src="../../Content/jQuery.Validation.js"></script>

That's basically all you need to do - include form validation on the client and server-side. The next section gives you an overview of the standard validators and their usage.

Standard Validators

The toolkit offers a handful of standard validators out of the box. The following table gives you an overview of the provided validators:

ValidatePresence Validates the presence of input value.

Sample:
new ValidatePresence("username")
ValidateDate Validates input value against the given date formats. Setting the DateFormats property to a comma-separated list of date formats, allows you to check if the value is formatted in one of the specified formats. You may check for date formats like MM/ DD/ YYYY. If DateFormats is not defined, then the validator will use the culture information of the current thread.

Sample:
new ValidateDate("startDate", "yyyy-mm-dd,yyyymmdd")
new ValidateDate("startDate") 
    { DateFormats = "yyyy-mm-dd,yyyymmdd" }
ValidateMin
ValidateMax
ValidateRange
Validates input value either against a minimum, maximum or integer range.

Sample:
new ValidateMin("step", 5)
new ValidateRange("step") { Min = 1, Max = 99 }
ValidateMinLength
ValidateMaxLength
ValidateRangeLength
Validates input value either against a minimum, maximum or integer range.

Sample:
new ValidateMaxLength("password ", 30)
new ValidateRangeLength("password") 
    { MinLength = 5, MaxLength = 30 } 
ValidateElement Joins multiple validators into one validator to keep things simple and allows the following to validate: Required, Min, Max, MinLength, MaxLength

Sample:
new ValidateElement("username") 
    { Required = true, MinLength = 5 } 
ValidateEqualTo Validates input value against another input value. This validator is useful to compare password inputs.

Sample:
new ValidateEqualTo("password", "passwordAgain") 
ValidateScriptMethod Validates input value using a custom JavaScript function and validation set class method.

Sample:
new ValidateScriptMethod("username") 
    { MethodName = "valUsername" }
new ValidateScriptMethod("username") {
MethodName = "valiUsername", 
    Parameters = "{Opt1:2, Opt2: "AB"}" } 

There are still some validators missing, e.g. a general regular expression validator or a specific email validator.

Validation Sets

Each validation set definition class derives from the ValidationSet base class. This base class contains and offers common functionality for the validation process. Let's take a look at the sample below to explain some possibilities the validation set offers to validate complex forms:

public class LoginValidationSet : ValidationSet {

   string Username = "";
   string Password = "";

   protected override ValidatorCollection GetValidators() {
      return new ValidatorCollection
      (
         new ValidateElement("username") 
            { Required = true, MinLength = 5, MaxLength = 30 },
         new ValidateElement("password") 
            { Required = true, MinLength = 3, MaxLength = 50 },
         new ValidateScriptMethod("username", "validateUsername")
      );
   }

   protected bool ValidateUsername() {
      // DO HERE SOME VALIDATION AND RETURN RESULT AS BOOLEAN VALUE
      return true;
   }

   protected override void OnValidate() {
      if(Username.StartsWith("billy") && Password.StartsWith("gat"))
         throw new ValidatorException("username", "The username/password combination ");
   }
}

Creating non-public instance member fields of type String like the Username or Password fields, allows the base class to populate those fields with the accompanying input field values. This is a simple way to access input values without checking the underlying values collection (e.g. Request.Form).

The ValidateScriptMethod validator defines a JavaScript function (validateUsername) to call during the client-side validation. This function must be defined or included in the HTML page. The ValidationSet base class checks during the server-side validation if the current validation set class contains a case-insensitive method named validateUsername.

Once all validators defined with the GetValidators method are called during the validation process, the base class will call an overall method called OnValidate. By overriding this method you can do some final validation. If you want to throw an exception you need to throw the ValidatorException with the field name and message as parameters.

Using the described techniques, the possibilities of the jQuery library and the custom validators (see below), you can validate most complex forms quite efficiently. The next section will describe ways to localize the messages.

Localization

It's easy to localize error messages of the toolkit using the standard folder. If the default settings are not changed, the default error message for each validator is stored in the ValidationSet.resx file (in the folder App_GlobalResources). The naming convention for the resource key is as follows: <VALIDATORNAME>_DefaultErrorMessage.

To change the default name of the ValidationSet.resx resource file, a derived validation set class can set the name by using the static field DefaultMessageResourceName or by adding the MessageResourceName attribute to the class. It is also possible to combine the techniques and use more than one resource file.

The sample site within the Validator Toolkit contains usage examples of localized error messages and field names. The localization is simple and straightforward.

Custom Validators

Creating custom validators is quite simple, but requires some basic knowledge of the jQuery JavaScript library and the validation plug-in if the validator wants to support client validation. The sample site includes a custom validator called ValidateBuga, which checks the input value against the constant string buga. Each validator derives from the Validator class, which provides a couple of virtual methods a custom validator must override:

GetClientMethodData This method defines by returning an instance of the ValidatorMethodData class the name of the custom validator (for the jQuery validation plug-in), the JavaScript function code and the default error message.
GetClientRule This method returns the plug-in client rule to use once the validator is defined within a validation set class.
GetClientMessage This method returns the localized error message for a given element.
GetDefaultErrorMessageFormat This method returns the default error message of the custom validator.
Validate This method validates the input value for the given element. If the input is not valid the validator must call the InsertError method of the Validator base class to signal an error.

Here is the source code of the ValidateBuga sample validator:

public class ValidateBuga : Validator {

   public ValidateBuga(string elementsToValidate)
      : base(elementsToValidate) {
   }

   public override ValidatorMethodData GetClientMethodData() {
      return new ValidatorMethodData(
         "buga",
         "function(value,element,parameters){return value=='buga';}",
         "$.format('" + ErrorMessageFormat + "')"
      );
   }

   public override string GetClientRule(string element) {
      return "buga:true";
   }

   public override string GetClientMessage(string element) {
      return string.Format("buga:'{0}'", GetLocalizedErrorMessage(element))
         .Replace("'", "\'");
   }

   protected override void Validate(string element) {
      if(Values.ContainsKey(element) == false || (Values[element] ??
         string.Empty).Trim() != "buga")
         InsertError(element);
   }

   protected override string GetDefaultErrorMessageFormat() {
      return "The field {0} must contain the value \"buga\"";
   }
} 

Another way to use custom validation is by using the validator ValidateScriptMethod. It allows to call a JavaScript function on the client-side and a specific method of the validation set class on the server-side. The custom validation is part of the validation set class and is not usable in multiple validation sets.

Summary

The Validator Toolkit is a simple and easy way to add client-side and server-side HTML form validation to the new ASP.NET MVC Framework. It is easy to extend the toolkit by adding custom validators. You may use the toolkit until Microsoft provides a solution for HTML form validation.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

Jürgen Bäurle
Software Developer (Senior)
Germany Germany
I’m a software developer based in Germany.
 
Homepage

Comments and Discussions

 
Generaluse validator for a Ajax form Pinmembertuanpm15-May-10 16:29 
GeneralValidation with sys.net.webrequest [modified] PinmemberNaveedAkram6-Feb-09 5:39 
Generalspecific email and/or regular expression validator PinmemberMats Jakobsson21-Jan-09 22:10 
QuestionA couple of little questions... PinmemberScott McKenzie13-Jul-08 14:21 
QuestionCode sample? Pinmemberolivier_ntk10-Jul-08 20:31 
Hi, nice job.
 
You mentioned that there are some code samples .. what is the link? danke schon!
AnswerRe: Code sample? PinmemberJuergen Baeurle10-Jul-08 21:24 
GeneralAttaching validation rules to elements where the ID is unknown at design-time PinmemberChristoff91526-Jun-08 7:21 
GeneralToolkit works now with ASP.NET MVC Preview Release 3 PinmemberJuergen Baeurle19-Jun-08 23:03 
QuestionjQuery version PinmemberPaulLinton14-Jun-08 1:51 
AnswerRe: jQuery version PinmemberPaulLinton15-Jun-08 13:13 
GeneralFix for typed viewdata Pinmember leppie 16-May-08 1:05 
QuestionHow to use space in the error messages PinmemberTony Mortana2-May-08 5:48 
GeneralTyped ViewData PinmemberMember 405884825-Apr-08 13:15 
QuestionWhat I would like to see... PinmemberSuperShade24-Apr-08 9:35 
QuestionWhat if I don't want to use jQuery? Pinmembertommy skaue23-Apr-08 3:05 
AnswerRe: What if I don't want to use jQuery? PinmemberJuergen Baeurle23-Apr-08 4:11 
GeneralError on id's containing "." Pinmemberarmasanea5-Apr-08 4:37 
GeneralError -question PinmemberStevieGen29-Mar-08 12:09 
GeneralRe: Error -question PinmemberStevieGen29-Mar-08 12:10 
AnswerRe: Error -question Pinmemberbszafko1-Apr-08 6:38 
GeneralRe: Error -question PinmemberStevieGen1-Apr-08 12:42 
QuestionValidation with External File? PinmemberSteveC-A914-Mar-08 5:01 
GeneralGood job PinmemberMaxGuernsey18-Feb-08 11:39 
GeneralRe: Good job PinmemberJuergen Baeurle18-Feb-08 12:28 
QuestionValidate objects directly? Pinmemberh52017-Feb-08 7:40 
AnswerRe: Validate objects directly? PinmemberJuergen Baeurle17-Feb-08 8:37 
GeneralWell done PinmvpDaniel Vaughan13-Feb-08 21:45 
GeneralRe: Well done PinmemberJuergen Baeurle13-Feb-08 22:56 
Generala Pinmembershashib2613-Feb-08 20:41 
GeneralRe: a PinmemberJuergen Baeurle13-Feb-08 22:55 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140926.1 | Last Updated 12 Feb 2008
Article Copyright 2008 by Jürgen Bäurle
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid