ASP.NET 2.0 Deeper into CustomValidator Part 2

This was something that I was not able to figure out back in some time when I blogged on this http://community.sgdotnet.org/blogs/chuawenching/archive/2007/03/09/ASP.NET-2.0-Deeper-into-CustomValidator.aspx

Now I found out the reason why? I will elaborate more.

Assuming you have a ValidationSummary control with the properties like below:

<asp:ValidationSummary ID="vlsFundApply" runat="server" HeaderText="The following field are invalid" ShowMessageBox="True" ShowSummary="False" />

 

All your errors will display in a MessageBox instead of a summary in the web form.

When you want to display the errors in a MessageBox, it also means that you cannot use the OnServerValidate to validate your control. You can only use the Client Script Validation in order for this to work. So you lose one thing, the flexibility to write your validation in C#.

Let focus on 2 examples which I will illustrate on validating using ClientValidationFunction. I know there are examples online that demonstrate how to use this attribute, but I will show you 2 real life examples which probably you will find it handy later in development. For advanced users, you can head straight down to conclusion.

1st example

Assuming you have this:

New IC **

:

[TextBox]

OldIC **

:

[TextBox]

OtherIC **

:

[TextBox]

Passport **

:

[TextBox]

** means you have to enter either 1 field or else will prompt you an error

Your custom validator control needs this attribute:

<asp:CustomValidator ID="csvIdentification" runat="server" ValidateEmptyText="true" Display="Dynamic" ErrorMessage="Personal ID" ClientValidationFunction="MultiICValidation">Please enter at least one of the Identification Field</asp:CustomValidator>

 

Then let’s assume you have a MasterPage and your web forms will use this MasterPage.

Place this piece of JavaScript code within the <head> of your MasterPage.

function MultiICValidation(sender, args)

        {

              if (document.all('_ctl0_ContentPlaceHolder1_txtNewIcNo1').value.length == 0

                      && document.all('_ctl0_ContentPlaceHolder1_txtNewIcNo2').value.length == 0

                      && document.all('_ctl0_ContentPlaceHolder1_txtNewIcNo3').value.length == 0

                      && document.all('_ctl0_ContentPlaceHolder1_txtIndividualOldIC').value.length == 0

                      && document.all('_ctl0_ContentPlaceHolder1_txtIndividualOtherID').value.length == 0

                      && document.all('_ctl0_ContentPlaceHolder1_txtIndividualPassport').value.length == 0)                 

                    args.IsValid = false;

                else

                    args.IsValid = true;

            }

Looks straightforward right J Remember this, you need the ClientID of the control (e.g. TextBox, Dropdownlist) not the UniqueID.

Also if you look at the “View Source” at your browser on runtime, you will see 2 kinds of IDs.

_ctl0_ContentPlaceHolder1_txtIndividualPassport

And

_ctl0$ContentPlaceHolder1$txtIndividualPassport

Always go for the 1st one.

There is another thing that you need to remember:

As you see above, you write a JavaScript method named MultiICValidation. In your CustomValidator attribute ClientValidationFunction,

NOT THIS

ClientValidationFunction=”return MultiICValidation();”

INSTEAD DO THIS

ClientValidationFunction=”MultiICValidation”

After all it is expecting a Function name.

2nd example

Assuming you have this:

Gender

:

[Dropdownlist]

 

With values like below:

 

Index = 0

Text = -- Select One –

 

Index = 1

Text = Male

 

Index = 2

Text = Female

 

So you need a CustomValidator to validate if say the user forget to choose a value, the default value will be index 0 which is “—Select One –“. You want to prevent this to happen.

Now you need a CustomValidator like this:

<asp:CustomValidator ID="csvGender" runat="server" ControlToValidate="ddlGender"

                        Display="Dynamic" ErrorMessage="Gender is required" ClientValidationFunction="GenderValidation">Purpose is required</asp:CustomValidator>

Paste the code below in your <head> element.

function PurposeValidation(sender, args)

{       

if (document.all('_ctl0_ContentPlaceHolder1_ddlGender').selectedIndex == 0)                   

                    args.IsValid = false;

                else

                    args.IsValid = true;

}

Simple right. Let’s move to the conclusion.

Conlusion:

You will notice that in order to make the errors to be display on a message box, I do not have any choices to use Client Script Validation to achieve this. You lose all the benefits on the managed side to code the validation logic. If you use the ShowSummary=”true”, then you enjoy both worlds – ClientValidation and ServerValidation.

Just one more thing before I end this conclusion.  Say you find it hard to maintain the javascript codes. Assuming you want to reuse it around your project. There are 2 ways which I can think of for now. Of course you can follow the technique which I used above. Just it will be quite messy in the head element if you have a lot of validations.

a) Create a standard JavaScript file which can be reused for the whole project

b) Create a method in the Global.asax which you can register a startup script using this.ClientScript.RegisterStartupScript. Of course if you choose to place this code in a class library, is possible as well. Take note, if you create such a reusable method you need to pass in the ClientID for each control. I will write a short snippet as below, but it will up for your creativity okay.

*You can probably run this inside the (!Page.IsPostBack) in Page_Load event

private void MultipleFieldValidation(params string[] args)

        {

            string jsFunctionName = "MultipleFieldJSValidation";

 

            if (args.GetLength(0) > 0)

            {

                StringBuilder jsBuilder = new StringBuilder();

                jsBuilder.Append("<script language=\"javascript\">\n");

                jsBuilder.Append("function " + jsFunctionName + "(sender, args)\n");

                jsBuilder.Append("{\n");

                jsBuilder.Append("\tif (");

 

                for (int i = args.GetLowerBound(0); i <= args.GetUpperBound(0); i++)

                {

                    if (i != args.GetLowerBound(0))

                    {

                        jsBuilder.Append(" && ");

                    }

 

                    jsBuilder.Append("document.all('" + argsIdea + "').value.length == 0");

                }

 

                jsBuilder.Append(")\n");

                jsBuilder.Append("\t\targs.IsValid = false;");

                jsBuilder.Append("\telse\n");

                jsBuilder.Append("\t\targs.IsValid = true;");

                jsBuilder.Append("}\n");

                jsBuilder.Append("</script>");

 

                this.ClientScript.RegisterStartupScript(typeof(Page), jsFunctionName, jsBuilder.ToString());

            }

        }

*For optimized performance, use StringBuilder instead of direct string concatenation.

Guess everything is possible with CustomValidator. Give it a try and let me know. Hope you find this as detail as possible and find it useful.

Published Friday, April 06, 2007 10:33 PM by chuawenching