Click here to Skip to main content
15,867,686 members
Articles / Web Development / HTML
Article

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

Rate me:
Please Sign up or sign in to vote.
4.98/5 (26 votes)
12 Feb 2008Ms-PL8 min read 246.5K   103   30
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:

C#
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:

C#
//
// 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:

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

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

HTML
<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:

HTML
<% 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:

HTML
<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:

ValidatePresenceValidates the presence of input value.

Sample:
C#
new ValidatePresence("username")
ValidateDateValidates 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:
C#
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:
C#
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:
C#
new ValidateMaxLength("password ", 30)
new ValidateRangeLength("password") 
    { MinLength = 5, MaxLength = 30 } 
ValidateElementJoins multiple validators into one validator to keep things simple and allows the following to validate: Required, Min, Max, MinLength, MaxLength

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

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

Sample:
C#
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:

C#
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:

GetClientMethodDataThis 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.
GetClientRuleThis method returns the plug-in client rule to use once the validator is defined within a validation set class.
GetClientMessageThis method returns the localized error message for a given element.
GetDefaultErrorMessageFormatThis method returns the default error message of the custom validator.
ValidateThis 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:

C#
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)


Written By
Software Developer (Senior)
Germany Germany
I’m a software developer based in Germany.

Homepage

Comments and Discussions

 
Generaluse validator for a Ajax form Pin
tuanpm15-May-10 16:29
tuanpm15-May-10 16:29 
GeneralValidation with sys.net.webrequest [modified] Pin
NaveedAkram6-Feb-09 5:39
NaveedAkram6-Feb-09 5:39 
Generalspecific email and/or regular expression validator Pin
Mats Jakobsson21-Jan-09 22:10
Mats Jakobsson21-Jan-09 22:10 
Hi,

Thank you for a great article, the validation system works great!

I have a couple of questions though:
1. Are you planning on creating a specific email and/or regular expression validator? And if, when? (really looking forward to it. Smile | :) )
2. I would like to feed my ValidationSet with a validatorcollection from a service layer, is this possible - and if so, how? In your examples you create the validatorcollection in the overriden GetValidators(), I would like to say something like:

public class FormValidationSet : ValidationSet
{
public IInputRowsService _service;

public FormValidationSet(IInputRowsService service)
{
_service = service;
}

protected override ValidatorCollection GetValidators()
{
return _service.GetValidators();
}

}
Does this make sense? Is it possible? Is it even relevant?

Thanks again!

BR
Mats J
QuestionA couple of little questions... Pin
Scott McKenzie13-Jul-08 14:21
Scott McKenzie13-Jul-08 14:21 
QuestionCode sample? Pin
olivier_ntk10-Jul-08 20:31
olivier_ntk10-Jul-08 20:31 
AnswerRe: Code sample? Pin
Jürgen Bäurle10-Jul-08 21:24
Jürgen Bäurle10-Jul-08 21:24 
GeneralAttaching validation rules to elements where the ID is unknown at design-time Pin
Christoff91526-Jun-08 7:21
Christoff91526-Jun-08 7:21 
GeneralToolkit works now with ASP.NET MVC Preview Release 3 Pin
Jürgen Bäurle19-Jun-08 23:03
Jürgen Bäurle19-Jun-08 23:03 
QuestionjQuery version Pin
PaulLinton14-Jun-08 1:51
PaulLinton14-Jun-08 1:51 
AnswerRe: jQuery version Pin
PaulLinton15-Jun-08 13:13
PaulLinton15-Jun-08 13:13 
GeneralFix for typed viewdata Pin
leppie16-May-08 1:05
leppie16-May-08 1:05 
QuestionHow to use space in the error messages Pin
Tony Mortana2-May-08 5:48
Tony Mortana2-May-08 5:48 
GeneralTyped ViewData Pin
Member 405884825-Apr-08 13:15
Member 405884825-Apr-08 13:15 
QuestionWhat I would like to see... Pin
SuperShade24-Apr-08 9:35
SuperShade24-Apr-08 9:35 
QuestionWhat if I don't want to use jQuery? Pin
tommy skaue23-Apr-08 3:05
tommy skaue23-Apr-08 3:05 
AnswerRe: What if I don't want to use jQuery? Pin
Jürgen Bäurle23-Apr-08 4:11
Jürgen Bäurle23-Apr-08 4:11 
GeneralError on id's containing "." Pin
armasanea5-Apr-08 4:37
armasanea5-Apr-08 4:37 
GeneralError -question Pin
StevieGen29-Mar-08 12:09
StevieGen29-Mar-08 12:09 
GeneralRe: Error -question Pin
StevieGen29-Mar-08 12:10
StevieGen29-Mar-08 12:10 
AnswerRe: Error -question Pin
bszafko1-Apr-08 6:38
bszafko1-Apr-08 6:38 
GeneralRe: Error -question Pin
StevieGen1-Apr-08 12:42
StevieGen1-Apr-08 12:42 
QuestionValidation with External File? Pin
IgDev14-Mar-08 5:01
IgDev14-Mar-08 5:01 
GeneralGood job Pin
MaxGuernsey18-Feb-08 11:39
MaxGuernsey18-Feb-08 11:39 
GeneralRe: Good job Pin
Jürgen Bäurle18-Feb-08 12:28
Jürgen Bäurle18-Feb-08 12:28 
QuestionValidate objects directly? Pin
h52017-Feb-08 7:40
h52017-Feb-08 7:40 

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

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