Monthly Archives: October 2008

Delegates in VB.NET

Delegates in VB.NET

Delegates are similar to function pointer in C, C++. Now,  if would be wondering what is pointer, if you have not know C, C++ or Java before.

Here, below is simple example

‘This is sample Class for example

Public Class ShabsSampleClass

    ‘This is sample method except as Parameter

    Sub DoSomeWork(ByVal strWork As String)

        Console.Write(strWork)

    End Sub

 

    ‘This is main function for this class

    Sub
Main()

        Dim strDiggingWork As String

        strDiggingWork = “Start Digging the Ground”

 

        DoSomeWork(strDiggingWork)

    End Sub

 

End Class

Here, in this function DoSomeWork, we have pass the String parameter. Now, you would be telling, what new in this, I already knew this. I know, even more, like you can pass class, object, multiple parameters and even param Arrays as parameter. So, what new in that!

Great, now, think of passing function as parameter. What did I say, some function as parameter, what does that mean.

It means, there would be some function like GetSomeWork which will accept function as parameter, and you will pass DoSomeWork as parameter to this function.

Yes, you can do this in .NET

I you didn’t know this, it would WOW for you. It happens to me itself.

When you are passing Function as parameter, it is known as Delegate.

All the event like mouseclick, keypress, ApplicationStart (in ASP.NET), etc are handling to some delegate in .NET. You won’t be knowing it, but VS IDE (Visual Studio Integrated Development Environment) does it for you.

Few things, you should know about the Delegate,

  1. Declaration Delegate is like normal Procedure/Method in VB.NET, which accepts parameter, but, doesn’t return anything.
  2. Delegate does not return any value. This is general statement, exceptions are there, but for now basic, keep in mind, they do not return any value.
  3.  
  4. Delegate have only declaration, they do not have any body.

  Public Delegate Sub SomeWorkDelegate(ByVal strSomeString As String)

    ‘Here, there would be no body for delegate, like it has for Sub

    ‘No END SUB here

  1. To use Delegate, you need to attach some function to it. Delegates own it own does nothing.

Here is the example to use Delegate

‘This is sample Class for example

Public Class ShabsSampleClass

    ‘This is sample method except as Parameter

    Sub DoSomeWork(ByVal strWork As String)

        Console.Write(strWork)

    End Sub

 

    ‘This is where, I create a Delegate with String Parameter

    Public Delegate Sub SomeWorkDelegate(ByVal strSomeString As String)

 

‘Here is some function, which will accept other function as parameter via some delegate

    Public Sub GetSomeWork(ByVal someDelegateFunc As SomeWorkDelegate)

        ‘call someDelegateFunc to so some owrk

        someDelegateFunc(“Here is the work”)

    End Sub

 

    ‘This is main function for this class

    Sub Main()

‘Declaring private delegate in this function with address of DoSomeWork function

Dim myWorkDel As SomeWorkDelegate = New

 SomeWorkDelegate(AddressOf DoSomeWork)

 

        ‘Using GetSomeWork function

        GetSomeWork(myWorkDel)

    End Sub

 

End Class

What the hell is this, I can’t understand a think! Don’t sweat, will explain you below

To understand this, let go line by line

1)      First Line

    Public Delegate Sub SomeWorkDelegate(ByVal strSomeString As String)

Here, in the line, you have declared a Delegate which will accept String as parameter.

Now, it like this will in future, will point to some function which would accept just one String as Parameter.

What, I have some function which have input as Two String Parameter, sorry, folks, can’t use this delegate to point to your function, you need to declare another Delegate which has input as two string Parameter

 

2)      First Function

‘Here is some function, which will accept other function as parameter via some delegate

    Public Sub GetSomeWork(ByVal someDelegateFunc As SomeWorkDelegate)

        ‘call someDelegateFunc to so some owrk

        someDelegateFunc(“Here is the work”)

    End Sub

Here, we have declared some function, which would accept another Function as parameter. It’s like I will accept some function as parameter, which has only one parameter as string.

(ByVal someDelegateFunc As SomeWorkDelegate)

This Parameter tell VB.NET, it expecting some function as parameter which as same signature as Delegate ‘SomeWorkDelegate’ i.e. Only One parameter as input, and that too, need to be String.

This mean, I can pass all the functions in the world to this function, which have one parameter, and that is String

This down, that the hell I am going to do with parameter which in Function by itself.

Well, there is some requirement, and I need to use this delegate function in my Function and hence, I am using it.

So, now, this function works only, when I pass some parameter as string. So,

someDelegateFunc(“Here is the work”)

This line, I am passing parameter as string.

What in this world, I need to do something like this. Well, if your world is some College Project or some novice Project, you don’t need to do this. This is because; you know all the function, which are there in your Project. You would directly use that, instead of doing this circus of declaring the delegate and using it.

But, you would some really Big project, like .NET framework itself, where there are 5000 classes and millions of function, and need to obey OOPS principle, and there are some 500 peoples working on this project, all across the Globe, i.e. there is some teams in US, India, Brazil, Canada, and so on! Here, you don’t know all the functions and need to add flexibility and scalability to you class you design.

 But, even, in college Project, it good to use it, as who know, the code which you have written would change the world, and puffs, you few lines project will grow to millions lines code, and your core class will be use by all other people.

If you have use delegates, you don’t need to rewrite you core class again to adapt to other classes which depend on your Class.

 

I know, this is getting bit stretchy, and it long, for you to read, so I need to wind up here.

3)      Main Function

    ‘This is main function for this class

    Sub Main()

‘Declaring private delegate in this function with address of DoSomeWork function

Dim myWorkDel As SomeWorkDelegate = New

 SomeWorkDelegate(AddressOf DoSomeWork)

 

        ‘Using GetSomeWork function

        GetSomeWork(myWorkDel)

    End Sub

Here, in main function is where, we are going to put every thing together.

Dim myWorkDel As SomeWorkDelegate = New

 SomeWorkDelegate(AddressOf DoSomeWork)

Here, in your main function, you are declaring delegate which is private variable. And to this variable, you are attaching the ‘DoSomeWork’ function to this delegate. Why?

Because, down the in this function, you are going to use this delegate.

Since, I know ‘SomeWorkDelegate’ has one parameter, that too string, and there is another function ‘DoSomeWork’ which too has just one parameter, and too string. I am attaching this function to this delegate.

        ‘Using GetSomeWork function

        GetSomeWork(myWorkDel)

Here, I want to use function GetSomeWork, which take Delegate ‘SomeWorkDelegate’ as parameter, hence, I would use this function with the ‘myWorkDel’ as parameter. ‘myWorkDel’ is just the private delegate you have declare in above line and attach ‘DoSomeWork’ it

So, what would happen in GetSomeWork.

This function will receive ‘myWorkDel’ as parameter, which will point to ‘DoSomeWork’ method. Hence, it would actual work it does is, this line below in GetSomeWork,

someDelegateFunc(“Here is the work”)

to compiler will look like

DoSomeWork(“Here is the work”)

And rest you know. There is even more in to this event and delegate, I would refer in other, let say Part II post! For you.

Advertisements

Best way to write Javascript Function

Here is always a new way of writing JavaScript Functions
Long were the days, when was start scripting for IE and Netscape. Firefox does not exist in that era and I got a bad habit of writing inline JavaScript functions like onclick=”javascript:alert(hi!);”

So, what is the best way to write JavaScript functions

1] onClick=”javascript: function(‘value’);”
2] onClick=”function(‘value’);”
3] onClick=”return function(‘value’);”

Well to start of,
1] First, onClick=”javascript: function(‘value’);”
I believe that putting JavaScript inline has been depreciated by W3C.

Not in HTML, but as braces cause problems with XML parsers you are encouraged to use only external scripts in XHTML.

The use of the javascript: pseudo-protocol identifier is probably unnecessary in most cases — just keep in mind that it is valid for those times when you may need to use it. The semicolon is also probably unnecessary in most cases but, again, I would recommend that you make a habit of always using it — as it is good programming practice to do so.

Please stop just making things up. Its a pseudo-protocol identifier because it’s aping the protocol part of a URL and it applies to a construction such as:

Open Sesame

And that construction was never really valid, though it used to work (and it doesn’t work anymore). And you will not find your construction in any HTML or JavaScript specification.

If you are coding of IE, it will work on all the version as it’s IE is very forgiving in terms of standards

2] Second, onClick=”function(‘value’);”
This is normal way of writing JavaScript. It will work on all W3C complaint browsers
There, in means simple, on clicking on function(‘value’), it will do some JavaScript function.
But, this function will not return any value, which will cancel that event.

In JavaScript, event raise by link, buttons, div, etc can be cancel if the return value is false
If you write
, here submit button will never submit form, as function is returning false.

But in above 2nd example, it will work as it doesn’t return any value.

3] Third, onClick=”return function(‘value’);”
As mention above, whenever you need to return value to the event, you will use return keyword with the function.
Here, note it, JavaScript is funny language, null, undefined, false and 0 means all the same thing for it.
So, when if(someobj) is evaluated, it will check for obj, if it doesn’t find it, it would return ‘undefined’ and javascript engine will consider it as false.
If some object is return, it doesn’t mean any of this value null, undefined, false and 0, and engine will evaluate true.
So, here the point is whatever your function return, and as long it’s not null, undefined, false, 0. Event won’t cancel and would be executed.
If you want more elaborate way of canceling the event, you could write
window.event.returnValue=false;
You could also read http://ryancannon.com/design/css_plus_js/cancelling-events-with-javascript where he has describe different way of canceling the event in JavaScript and which browser support it.

ASP.NET Validation in depth from MSDN

ASP.NET Technical Articles
ASP.NET Validation in Depth

 

Anthony Moore
Microsoft Corporation

October 2000
Updated March 2002

Summary: A detailed examination of the workings of ASP.NET validation Web controls. (15 printed pages)

Contents

Introduction
In the Beginning
What Happens When?
Server-Side Validation Sequence
Client-Side Validation
Validity Rules and Meaningful Error Messages
Effect of Enabled, Visible, and Display Properties
The CustomValidator Control
Which Controls Can Be Validated?
That’s It

Introduction

This article discusses in detail how the ASP.NET validation controls work. This article is recommended reading for anyone building complex pages with validation controls or those looking to extend the validation framework. For people looking to get started with the validation controls or deciding whether to use them, see User Input Validation in ASP.NET [ http://msdn.microsoft.com/en-us/library/ms972961.aspx ] .

In the Beginning

Throughout the development of ASP.NET, we knew that helping out with validation was important. Take a look at most commercial Web sites today and you will notice that they are filled with forms that clearly execute a lot of handwritten code to perform validation. Validation code is not particularly sexy to write. It can be exciting to write code to display tables of data or to dynamically generate charts, but no one gets their coworkers to check out the cool way they stopped someone from entering a blank value for a name field.

Validation of Web applications is particularly frustrating for other reasons as well. HTML 3.2 is so limited in what you can control and what feedback you get from the user that you can’t apply the same tricks you can use on a richer client, such as preventing the user from entering certain characters, or making beep sounds. It is possible to create more powerful validation using browser script. This can be hard to justify, however, because script is not always present in client browsers and can be bypassed by malicious users. It is necessary, therefore, to implement the same checks on the server anyway, in order to have a secure site.

In the development of ASP.NET, our original intention was to have just one control to handle validation, which would have been a version of the TextBox control that could also display errors. When the time came to design the control, however, it became clear that this would not cut the mustard. We looked at a large number of data-entry forms and tried to find a solution that would fit as many of them as possible. We found a number of interesting things about data-entry forms:

  • It is common to have error messages or icons adjacent to input elements, but they are almost always positioned in different table cells.
  • It is common to have an area of the page where all errors are summarized.
  • Many sites contain client-side script to provide more immediate feedback and prevent wasted round-trips to the server.
  • Many sites that have client-side script display message boxes if there were errors.
  • It is not just text inputs that are validated. Drop-down lists and radio buttons are also frequently validated.
  • When a field is empty, sites generally display a message or icon that is different from the one they display when the entry is invalid.
  • Many validation checks are excellent candidates for regular expressions.
  • It is common for validity to be dependent on comparisons between inputs.
  • Among validation tasks, 90 percent or more are common operations like checking names and ZIP codes. Most sites seemed to be reinventing the wheel.
  • There is generally too much variation between sites to have a perfect solution that can do 100 percent of validation tasks for every site.

Consideration of all these points led to the eventual solution of the five Validator controls, the ValidationSummary control, and integration with the Page object. It was also clear that the solution needed to be extensible, and there needed to be an API for working with it on both the client and the server.

When we looked at the different sorts of validation that takes place, it seemed like we would need a bigger toolbox. In most component environments like Microsoft® ActiveX®, we probably would have tried to overload the functionality of all the validation controls into one control that worked with different properties in different modes. However, thanks to the magic of inheritance in the Microsoft® .NET Framework, it is possible to provide a suite of controls that do specific validation with specific properties, because the overhead of deriving each new control is very small.

Most of the work done by these controls is implemented in their common parent, BaseValidator. You can also derive from BaseValidator or the other controls to take advantage of this. In fact, even BaseValidator is too lazy to implement its own Text property and inherits from Label.

What Happens When?

It is beneficial to understand the sequence of events when a page with validation Web controls is processed. If any of the validation conditions are optional, you will want to know exactly when validation takes place on both the client and the server. If you are writing your own validation routines that are potentially time-consuming or that have side effects, it is also important to have an idea of when they will be called.

First, let’s look at the server.

Server-Side Validation Sequence

It is important to understand the life cycle of a page. For those used to working with forms in Visual Basic or similar rich client tools, it takes a bit of getting used to. A page and all the objects on it do not actually live for as long as a user is interacting with them, although it can sometimes seem like they do.

Here is a simplified sequence of events when a page is first accessed:

  1. Page and its controls are created, based on ASPX file.
  2. Page_Load event fires.
  3. Page and control properties are saved to a hidden field.
  4. Page and controls are turned into HTML.
  5. Everything is thrown away.

Now, when a user clicks on a button or similar control, it goes back to the server and does a similar sequence. This is called the post-back sequence:

  1. Page and its controls are created based on ASPX file.
  2. Page and control properties are recovered from hidden field.
  3. Page controls are updated based on user input.
  4. Page_Load event fires.
  5. Change notification events fire.
  6. Page and control properties are saved to a hidden field.
  7. Page and controls are turned into HTML.
  8. Everything is thrown away again.

Why don’t we just keep all objects in memory? Because Web sites build with ASP.NET would not work with very large numbers of users. This way, the only objects in memory on the server are things being processed right now.

When does server-side validation take place? Well, it does not take place at all on the first page fetch. Most of our end-users are very diligent, and we want to give them the benefit of the doubt that they will fill in the form correctly before we bombard them with red text.

On the post-back, validation takes place during step 5, just before the event fires for the button or control that triggered the validation. Button controls in ASP.NET have a property called CausesValidation that defaults to True. It is the action of clicking on buttons that makes validation happen. The best place to check the results of validation is in the event handler that triggered the validation. You can also have buttons with CausesValidation=False, that will not cause any validators to be evaluated.

One potentially confusing thing about this timing is that the validators will not have been evaluated at the time Page_Load is triggered. The benefit of this is that it gives you a chance to programmatically change property values affecting the validity of the page, such as enabling or disabling certain validators.

If this timing is not to your liking and you prefer to evaluate everything in Page_Load, you can do this by explicitly triggering the validation during this event by calling Page.Validate. After this has been called you can then check the result of Page.IsValid. If you try to query the result of Page.IsValid before Page.Validate has been called, either explicitly or being triggered by a button with CausesValidation=True, then its value is meaningless, so an exception will be thrown.

The Page API

The Page object has some important properties and methods with respect to server-side validation. They are summarized in Table 1:

Table 1. Page object properties and methods

Property or Method Description
IsValid property This is the most useful property. It allows you to check whether the entire form is valid. This is generally done before performing a database update. It is true only if all the objects in the Validators collection are valid, and it does not cache this value.
Validators property A collection of all the validation objects for the page. It is a collection of objects that implement the IValidator interface.
Validate method A method that is called at validation time. The default implementation on Page goes to each validator and asks it to evaluate itself.

The Validators collection is useful for a number of things. It is a collection of objects of that implement the IValidator interface. I use the term objects rather than controls because the Page cares only about the IValidator interface. While it happens that all the validators will generally be visual controls that implement IValidator, there is no reason someone cannot come along with an arbitrary validation object and add it to the page.

The IValidator interface has the following properties and methods:

Table 2. IValidator interface properties and methods

Property or Method Description
IsValid property Indicates whether or not the validation check made by the individual validating object has passed. You can manually alter this value after validation has taken place.
ErrorMessage property Describes the error that the validation object is validating and that may be displayed to the user.
Validate method Executes the validation check of the validation object to update its IsValid value.

You can do some interesting things with this interface. For example, to reset the page to a valid state, use the following code (examples shown in C#):

 IValidator val;































 foreach(val in Validators) {































 Val.IsValid = true;































 }































To re-execute the whole validation sequence, use the following code:

 IValidator val;































 foreach(val in Validators) {































 Val.Validate();































 }































This is equivalent to calling the Validate() method on Page.

Another way to make some changes before validation takes place is to override the Validate method. This example shows a page that contains a validator that is turned on or off based on the value of a checkbox:

 public class Conditional : Page {































 public HtmlInputCheckBox chkSameAs;































 public RequiredFieldValidator rfvalShipAddress;































































 public override void Validate() {































 // Only check ship address if not same as billing































 bool enableShip = !chkSameAs.Checked;































 rfvalShipAddress.Enabled = enableShip;































 // Now perform validation































 base.Validate();































 }































 }































Client-Side Validation

If client-side validation is enabled for your page, a whole different sequence occurs in-between the round trips. Client-side validation works using client JScript®. No binary components are needed to make it work.

While the JScript language is reasonably well standardized, the Document Object Model (DOM) for interacting with HTML documents in browsers did not have a widely adopted standard at the time these components were developed and tested. As a result, client-side validation only takes place in Internet Explorer 4.0 and later, because it targets the Internet Explorer DOM.

From a server point of view, client-side validation just means that the validation controls emit different stuff into the HTML. Other than that, their sequence of events is exactly the same. The server-side checks are still carried out. This may seem redundant, but it is important because of the following:

  • Some validation controls may not support client scripting. A good example: if you are using a CustomValidator with a server validation function but no client validation function.
  • Security considerations. Someone can very easily take a page with script and disable or change it. You should not rely on script to stop bad data getting into to your system, only to provide more immediate feedback to your users. For this reason, if you are using a CustomValidator, you should not provide a client validation function without a corresponding server validation function.

Every validation control makes sure that a standard block of client script is emitted into the page. This is actually just a small amount of script that includes a reference to code in a script library called WebUIValidation.js. This file, which is downloaded separately and can be cached by the browser, contains all of logic for client-side validation.

About the Script Library

Because the validation Web controls script that is in a script library, it is not necessary to emit all of the code for client-side validation directly into the page, although it acts as though this is what has happened. The main script file reference looks like this:


By default, the script file will be installed into your default root in the aspnet_client directory, and it is referenced using a root-relative script include directive, which begins with the forward slash. This reference means that each individual project does not have to include the script library inside it, and all pages on the same machine can reference the same file. You will notice that it also has the common language runtime version number in the path, so that different versions of the runtime can run on the same machine.

If you take a look around your default virtual root, you can find this file and take a look inside it. The location of these files is specified in the machine.config file, an XML file used for most ASP.NET settings. Here is the definition of the location within that file:

 

You are encouraged to read the script to see more of what is going on. However, it is not recommended that you modify these scripts, because their function is very closely tied to a particular version of the run time. If the run time is updated, the scripts may need a corresponding update, and you will have to either lose your changes or face problems with the scripts not working. If you must change the scripts for a particular project, take a copy of the files and point your project to them by overriding the location of the files with a private web.config file.It is perfectly fine to change this location to be a relative or absolute reference.

Disabling Client-Side Validation

There are some cases where you may not want client-side validation. If the number of input fields is very small, client-side validation may not be of much benefit. You may have logic that needs a round trip to the server every time anyway. You may find that the dynamically appearing messages on the client have an adverse affect on your layout.

Note   The way to disable client-side validation is to set the EnableClientScript property of the validator or ValidationSummary control to False. It is possible to have a mixture of server-only and client-sever validation components on the same page.

The Client-Side Sequence

This is the sequence of events when a page with client-side validation runs:

  1. As the page is loaded into the browser, there is some initialization done on each validation control. The controls are emitted as tags with HTML attributes that correspond closely to their properties on the server. The most important thing that happens here is that any input elements referenced by the validators are “hooked up.” The referenced input elements have their client events modified so that the validation routines are called whenever the input is changed.
  2. Code in the script library will be executed as users tab from field to field. The validation conditions are re-evaluated when a dependent field is changed, and the validator is made visible or invisible as appropriate.
  3. When the user pushes a button that has the CausesValidation property set to True, the validators are all re-evaluated. If they are all valid, then the form is posted to the server. If there are one or more errors, a number of things happen:
    • The submit is cancelled. The form does not get posted back to the server.
    • Any invalid validators become visible.
    • If there is a validation summary with ShowSummary=true, it will collect all the errors from the validation controls and update its contents with them.
    • If there is a validation summary with ShowMessageBox=true, it will collect the errors and display them in client message box.

Because they are executed whenever the inputs change as well as at submit time, client side validation controls generally evaluate two or more times on client. Remember that they will still be re-evaluated on the server once the submit takes place.

The Client-Side API

There is a mini-API that you can use on the client to achieve various effects with your own client-side code. Because it is not possible to make certain routines hidden, you can theoretically make use of any of the variables, attributes, and functions defined by client-side validation script. However, many of them are implementation details that may be changed. Here is a summary of the client-side objects that we encourage you to use.

Table 3. Client-side objects

Name Type Description
Page_IsValid Boolean variable Indicates whether the page is currently valid. The validation scripts keep this up to date at all times.
Page_Validators Array of elements This is an array containing all of the validators on the page.
Page_ValidationActive Boolean variable Indicates whether validation should take place. Set this variable to False to turn off validation programmatically.
isvalid Boolean property This is a property on each client validator indicating whether it is currently valid.

Bypassing Client Validation

A common task you may need to do is to have a “Cancel” button or a navigation button on a page. In this case, set the CausesValidation property on the button to False and no validation will take place, either on the server or the client. If you lay out a page like this, you will want to check Page.IsValid in your button even handlers. If you instead call Page.Validate during Page_Load, you will not have a way of knowing whether a submit or cancel button was pushed.

Special Effects

Another common requirement is to have effects other than the error messages displayed by the validators themselves in error situations. In this case, any modifications in behavior you make need to be made on both the server and the client. Suppose you want to have a Label that changes color depending on whether an input is valid. Here is how you would do this on the server:

public class ChangeColorPage : Page {































 public Label lblZip;































 public RegularExpressionValidator valZip;































 































protected override void OnLoad(EventArgs e) { 































 Page.Validate(); 































 lblZip.ForeColor = valZip.IsValid? Color.Black : Color.Red;































 } 































}
































This is all very nice, but whenever you modify validation like this, you may find that it looks inconsistent unless you do an equivalent operation on the client. The validation frameworks saves you from a lot of this double effort, but for extra effects you just have to do it in two places. Here is a client fragment that does the same thing:

 

































Client-Side APIs

Some additional scenarios are enabled by functions that can be called from your client-side script.

Table 4. Functions called from client-side script

Name Description
ValidatorValidate(val) Takes a client-validator as input. Makes the validator check its input and update its display.
ValidatorEnable(val, enable) Takes a client-validator and a Boolean value. Enables or disables a client validator. Being disabled will stop it from evaluating and it will always appear valid.
ValidatorHookupControl(control, val) Takes an input HTML element and a client-validator. Modifies or creates the element’s change event so that it updates the validator when changed. This can be useful for custom validators that depend on multiple input values.

Of particular use is to be able to enable or disable validators. If you have validation that you want active only in certain scenarios, you may need to change the activation on both server and client, or you will find that the user cannot submit the page.

Here is the previous example with a field that should only be validated when a check box is unchecked:

 public class Conditional : Page {































 public HtmlInputCheckBox chkSameAs;































 public RequiredFieldValidator rfvalShipAddress;































 public override void Validate() {































 bool enableShip = !chkSameAs.Checked;































 rfvalShipAddress.Enabled = enableShip;































 base.Validate();































 }































 }
































Here is the client-side equivalent:

Same as Billing

Validity Rules and Meaningful Error Messages

Each validator displays a specific error message about a specific condition on a specific control. There are rules as to what is considered valid that may at first seem confusing to you as a developer, but they are necessary to allow you to construct error messages that are actually helpful to the user.

All of the validators (except for RequiredFieldValidator) are considered valid if they are blank. If a blank value is not valid, you generally need to provide a RequiredFieldValidator in addition to another validator. You need to do this because almost universally you want different error messages for the blankness and for the validity. Otherwise, you end up with confusing messages like “You must enter a value and it must be between 1 and 10.”

Another special rule relates to CompareValidator and RangeValidator when the input fields cannot be converted to the specified data type. The evaluation of validity for the CompareValidator with ControlToCompare specified goes like this:

  1. If the input field referenced by ControlToValidate is blank, it is valid.
  2. If the input field referenced by ControlToValidate cannot be converted to the data type, it is invalid.
  3. If the input field referenced by ControlToCompare cannot be converted to the data type, it is valid.
  4. The inputs fields are converted to the data type and compared.

The third step may seem a little counterintuitive. The step works this way because it would be hard to write a meaningful error message for the validator if it were checking the validity of more than one field at a time. A separate validator should be used to report on error conditions in the ControlToCompare input field. RangeValidator works in a similar way with its maximum and minimum properties.

Effect of Enabled, Visible, and Display Properties

The difference between the Enabled, Visible, and Display properties on validators may not be immediately obvious.

Display=None can be used to specify a validator that does not display anything directly, but still gets evaluated, still affects overall validity, and can still put an error in the summary on both client and server. For client-side validation, these values determine whether the visibility or the display style attributes are used to turn the validator on or off. For server-side validation, Display=Dynamic means that nothing at all displays when the input is valid, while Display=Static means that a single nonbreaking space (“ ”) is emitted. This last behavior exists so that table cells containing only validators do not collapse to nothing when valid. Why not just use Visible=false to have an invisible validator? In ASP.NET the Visible property of a control has a very strong meaning: a control with Visible=false will not be processed at all for pre-rendering or rendering. As a result of this stronger meaning, Visible=false for a validator means that not only does not it not display anything, it is does not function either. It is not evaluated, does not affect page validity, and does not put errors in the summary. Enabled treads middle ground here. For the most part, Enabled=false has the exact same effect as Visible=false. However, in client-side validation, a disabled validator is still sent to the browser, but in a disabled state. You can activate it with the ValidatorEnable function in client script. When using Visible or Enabled to control whether validation takes place, bear in mind the sequence of events on the server above. Either change them before validation takes place, or re-validate afterwards. Otherwise, their IsValid values may not reflect the changes to their properties. The CustomValidator Control The easiest way to extend the validation framework is to use the CustomValidator control. This can be used either to perform validation that is not covered by something another validation control can do or to perform validation that requires access to information on the server, such as a database or Web service. If you add a CustomValidator with just a server validation function defined, you will notice that it does not take part in client-side validation. The CustomValidator is not updated as users tab between fields, and it requires a round trip to the server to perform its validation. If you are using a CustomValidator to perform a check that does not need any information that lives on the server, you can also have your validator fully participate in client-side validation by using the ClientValidationFunction property. It is assumed that if you provide a ClientValidationFunction, it should ideally perform exactly the same checks as your server validation handler. Failing that, it should perform a subset of that verification. Don’t have a client validation function that does more verifications than are performed on the server, as hackers will be able to bypass it easily. Here is a simple example of a CustomValidator that works on the client and the server that just checks to see that the input is an even number. First, here is the server function (in C#):protected void ServerValidate(object source, ServerValidateEventArgs args) { try { int i = Int32.Parse(args.Value); args.IsValid = ((i % 2) == 0); } catch { args.IsValid = false; } } Here is how it is declared on the client, along with a client validation function that performs the same check. This would usually be in JScript, although it can also be VBScript® if you are targeting Microsoft® Internet Explorer. Input: Here are some points to note about using CustomValidator: Like all the other validation controls (besides RequiredFieldValidator), it is considered valid if the input field is blank. For older browsers or when client validation is turned off, your client validation function will not get called. You don’t have to check the browser capabilities yourself before defining the function, but you do need to make sure it does not cause script errors just by being defined. Always enclose your client code in an HTML comment, as in the example. Two parameters are passed into your client function, corresponding to the parameters that are passed to the server function. The first is the client validator element, and the second is the equivalent of the arguments on the server. It has two properties, the Value, which contains the input to be validated and IsValid, which you can update to indicate validity. You can leave the ControlToValidate blank. In this mode, the server function always fires once per round trip and the client function always fires once for each attempt to submit. You can use this to validate controls that cannot otherwise be validated, such as a CheckBoxList or stand-alone radio buttons. It can also be useful when the condition is based on multiple controls and you don’t want it evaluated as the user tabs between fields on the page. You can also hook up the change events of more than one control. You can do this by having some inline script that calls the client function ValidatorHookupControl, described above. Which Controls Can Be Validated? In order to be referenced by a validation control, a control must have a validation property. All controls that can be validated have a ValidationPropertyAttribute, which indicates which property should be read for the purposes of validation. If you write your own control, you can make it take part in validation by providing one of these attributes to specify which property to use. For validation to work client-side as well, this property must correspond to the value attribute of the HTML element that gets rendered on the client. Many complex controls such as DataGrid and Calendar do not have a value on the client and can only be validated on the server. This is why only controls that correspond closely to HTML elements can be involved in validation. Also, a control must have a single logical value on the client. This is why RadioButtonList can be validated, but CheckBoxList cannot. That’s It This is probably more than you wanted to know about ASP.NET validation. Have fun with it!