Thursday, December 31, 2009

AJAX - The Classical way

AJAX is an acronym that stands for Asynchronous JavaScript and XML. AJAX gains its popularity by allowing data on a page to be dynamically updated without having to make the browser reload the page. I will describe more about how AJAX works, and then go into some sample code to try out.

This term has been made famous by some of Google's latest web apps. At the top of this list is Google Suggest, which gives you suggestions (go figure) on what you are searching for as you type based on popularity of the search term. If you aren't familiar with Google Suggest, check it out.

Microsoft too started its own R&D in this area. In its early development stages, ASP.NET AJAX was given the code name Atlas. Initial releases were made public to the development community in the form of CTPs (Community Technical Previews). The production version, ASP.NET AJAX 1.0 RTM; was released on January 23, 2007. as an extension to ASP.NET 2.0.

Important release milestones for ASP.NET AJAX are as follows:
CTPs - October, December 2005, January, March, April, June, July 2006
Beta - October, November 2006
Release Candidate (RC) - December 2006
ASP.NET AJAX 1.0 RTM - January 23, 2007
ASP.NET AJAX 3.5 - November 19, 2007 (as part of ASP.NET 3.5)

The next version, ASP.NET AJAX 4.0; will be part of the ASP.NET 4.0 framework release which will be available from around Feb 2010. ASP.NET AJAX runs on the following browsers:
Microsoft Internet Explorer (>= 6.0)
Mozilla Firefox (>= 1.5)
Opera (>= 9.0)
Apple Safari (>= 2.0)
Google Chrome

At present, the ASP.NET AJAX suite consists of the following components and packages:
Microsoft Ajax Library 3.5, which is a JavaScript library that provides the client-side features of the ASP.NET AJAX framework. Integrated in ASP.NET 3.5, the library is also available as a separate download for use in other environments, such as PHP.
A server framework – included in ASP.NET 3.5 – for building Ajax-enabled ASP.NET server controls. These components are also available for ASP.NET 2.0 in a separate package called ASP.NET 1.0 Extensions.
ASP.NET 2.0 AJAX Templates, a package with a set of Visual Studio templates for building ASP.NET AJAX applications with ASP.NET 2.0 and Visual Studio 2008.
ASP.NET AJAX Preview, a package with the new features that will be part of the future versions of the framework.

The Classic Way
---------------

There is more going on here than just AJAX however. The actual drop down list is an additional DHTML piece that we will not be covering in this article.

Is AJAX a new technology? Yes and no would both be incorrect answers. A proper answer would be a new application of current technologies, with emphasis on plurality. This list of technologies includes standard HTML controls, JavaScript, an XML HTTP component, and XML data structures.

The Steps
---------

The following is an outline of the sequence of events when using AJAX:
Web page is rendered
A trigger executes a JavaScript function call (i.e. onKeyUp, button click, setTimeout, page load, etc.)
JavaScript instantiates an XML HTTP object
XML HTTP object calls a remote page
Remote Page transforms an XML structure using XSLT and returns the result
JavaScript accepts the results and applies it to the page
Tada! No page reload, just magical dynamic data

Get To It Already!
------------------

These steps are great, but without a sample application it is tough to envision. Being the responsible author that I am, I have of course included a sample of the steps discussed.

I think that it is important to discuss the XML HTTP object to gain a better understanding of what is going on here. XML HTTP allows code to connect to a remote location and perform GET and POST requests asynchronously. This means that we can connect to a remote host, send a request, and continue on with additional logic. When the remote host returns a response, a function designated to handle the return event is able to accept the data and make decisions based on what was received. The data passed to and from the remote host does not have to be in an XML format. XML is simply a well-formatted string. I have found on multiple occassions that passing a string that is not in an XML format is most appropriate for the given task. The XML HTTP object will not be compatible on all browsers or operating systems. Being that this is a client side function the client machine is responsible for the implementation as opposed to the server.

I have been utilizing this object since ASP 3.0 for making remote calls from a web page. Imagine the power here. Data and processes are accessed on disparate locations without the client ever having to leave the comfort of the domain or page that he/she is on.

The JavaScript
--------------

The JavaScript is the real meat and potatoes in AJAX. It handles the change detection, data request and receipt, and placing the data on the page.

Be sure to update the requestURL variable with the path that you will be accessing the aspx file from.

The following is the JavaScript code used:

<-script>
var xmlHttp;
var requestURL = 'http://localhost/misctest/getusernames.aspx?q=';
var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5")!=-1) ? 1 : 0;
var is_opera = ((navigator.userAgent.indexOf("Opera6")!=-1)||(navigator.userAgent.indexOf("Opera/6")!=-1)) ? 1 : 0;
//netscape, safari, mozilla behave the same???
var is_netscape = (navigator.userAgent.indexOf('Netscape') >= 0) ? 1 : 0;

function show_data(strName){
if (strName.length > 0){
//Append the name to search for to the requestURL
var url = requestURL + strName;

//Create the xmlHttp object to use in the request
//stateChangeHandler will fire when the state has changed, i.e. data is received back
// This is non-blocking (asynchronous)
xmlHttp = GetXmlHttpObject(stateChangeHandler);

//Send the xmlHttp get to the specified url
xmlHttp_Get(xmlHttp, url);
}
else {
//Textbox blanked out, clear the results
document.getElementById('nameList').innerHTML = '';
}
}

//stateChangeHandler will fire when the state has changed, i.e. data is received back
// This is non-blocking (asynchronous)
function stateChangeHandler()
{
//readyState of 4 or 'complete' represents that data has been returned
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 'complete'){
//Gather the results from the callback
var str = xmlHttp.responseText;

//Populate the innerHTML of the div with the results
document.getElementById('nameList').innerHTML = str;
}
}

// XMLHttp send GET request
function xmlHttp_Get(xmlhttp, url) {
xmlhttp.open('GET', url, true);
xmlhttp.send(null);
}

function GetXmlHttpObject(handler) {
var objXmlHttp = null; //Holds the local xmlHTTP object instance

//Depending on the browser, try to create the xmlHttp object
if (is_ie){
//The object to create depends on version of IE
//If it isn't ie5, then default to the Msxml2.XMLHTTP object
var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';

//Attempt to create the object
try{
objXmlHttp = new ActiveXObject(strObjName);
objXmlHttp.onreadystatechange = handler;
}
catch(e){
//Object creation errored
alert('IE detected, but object could not be created. Verify that active scripting and activeX controls are enabled');
return;
}
}
else if (is_opera){
//Opera has some issues with xmlHttp object functionality
alert('Opera detected. The page may not behave as expected.');
return;
}
else{
// Mozilla | Netscape | Safari
objXmlHttp = new XMLHttpRequest();
objXmlHttp.onload = handler;
objXmlHttp.onerror = handler;
}

//Return the instantiated object
return objXmlHttp;
}

function UseValue(strVal){
document.frmStuff.txtName.value = strVal;
}
<-/script>

The Client Page (HTML)
----------------------

The client page, excluding the JavaScript, is about as basic as it gets. A simple form with an onKeyUp event in a text box is all that is really required. I included a DIV tag to display the resulting data. The HTML has been provided:

<-html>
<-head>
<-title>Ian Suttle's AJAX Sample<-/title>
<-style>
body, input {font-family: arial; font-size: 12px;}
<-/style>

// Insert JavaScript Here

<-/head>
<-body>
<-form name="frmStuff" id="Form1">
<-table border="0" cellpadding="4" cellspacing="0" id="Table2">
<-tr>
<-td width="100">Name:<-/td>
<-td><-input type="text" name="txtName" id="txtName" autocomplete="off" onkeyup="show_data(this.value);"><-/td>




<-tr>
<-td width="100" valign="top">Suggestions:<-/td>
<-td>
<-div id="nameList"><-/div>
<-/td>
<-/tr>
<-/table>
<-/form>
<-/body>
<-/html>

The Remote Page
---------------

When a request is made from the JavaScript, it makes contact with the "remote page." A query string variable, "q", is included representing the data that was keyed by the user. I am going to construct an XML string, only including those elements that are valid based on the search term. To relieve the client side script from doing any formatting, I have applied an XSL transformation on the XML data. Formatting the XML on the server side is a much better solution than formatting within the JavaScript on the client side. A major point to recognize is that certain browsers will not support XML and XSL objects. Assuming you want your data to always be formatted the same, stick with the server side logic.

Create a page called GetUsernames.aspx. Be sure to remove ALL HTML from the page except the required @Page line. The code-behind will create the output to display on the page. Add the following code to the code-behind file:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;

namespace MiscTest
{
///
/// Summary description for GetUsernames.
///

public class GetUsernames : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
GetUsernameList();
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///

private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion

private void GetUsernameList()
{
//Get the request query
string strQuery = Request["q"].ToString();

//Create the XML-like string to be sent back to the request
string strXmlNames = "";

//An arbitrary array of names that will be written to an XML Document.
string[] arrStrNames = new string[5]{"Ian Suttle", "John Doe", "Alex Wright", "Albert Einstein", "Sierra Tracy"};

//Loop through the names, creating a psuedo XML element for each
foreach(string strName in arrStrNames)
{
//If the request matches the beginning of a name, then add it to the string
// otherwise it shouldn't be a valid match
if (strName.ToLower().Substring(0, strQuery.Length) == strQuery.ToLower())
strXmlNames += "" + strName + "";
}

//Prepend and append the parent element
strXmlNames = "" + strXmlNames + "";

//Create an XmlDocument object to store the XML string that we created
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(strXmlNames);

//Create a navigator object to use in the XSL transformation
XPathNavigator xPathNav = xDoc.CreateNavigator();

//Create the XSLTransform object
XslTransform xslt = new XslTransform();
xslt.Load(Server.MapPath("Names.xslt"));

//Do the transformation and send the results out to the Response object's output stream
xslt.Transform(xPathNav, null, Response.OutputStream);
}
}
}

The XSL Stylesheet
------------------

The XSL document is used to format the XML data to a defined presentation. The code to do the transformation is included here, although great detail on how this works is not the topic of this article. Create a new XSL document called Names.xslt and paste the following code into it:

<-?xml version="1.0" encoding="UTF-8" ?>
<-xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<-xsl:template match="/">
<-xsl:for-each select="users/user">
<-xsl:value-of select="name" />

<-/xsl:for-each>
<-/xsl:template>
<-/xsl:stylesheet>

Conclusion
----------

So once again, AJAX is nothing more than an application of technologies that have been around for a number of years. ASP.NET isn't the wizard behind this curtain. There is nothing here that can't be done in ASP Classic and JavaScript. Not that given a choice one would revert to ASP Classic :). Additionally, ASP.NET will have a completely different approach to making remote calls from a page.

The possible implications of AJAX are very impressive. Updating notices, checking email, monitoring processes, etc... The limits of application are virtually up to the imagination of the developer.

Monday, December 28, 2009

Using Cookies in Asp.Net



This article tells about cookies and how to write and read cookies in ASP.NET web application.

Cookies are small amounts of text that can be stored on the client pc by the browser.  The cookie can be accessed both at the client through the use of Javascript and also at the server.  While cookies can be a convenient way to store small bits of state information, it's important to keep in mind that the client browser may have been configured not to accept cookies.

In each cookie you can not save more than 4k of information. Remember clients can open cookies and see the content of a cookie so never save a password there. Cookies are usually used to save user preference information.



Cookies are used to store user specific information in form of text strings. When a user visits particular website some user specific information gets stored and this information can be retrieved later when the same website gets visited from same machine and can be sent to server. Cookies are associated with websites instead of individual pages.

Web developers can use cookies to store user preference and renders the customized page on next visit according to user's interest. There are browser imposed limitations regarding size of cookies and number of cookies per website which can be stored.


In ASP.NET cookies can be created using class HttpCookie in System.Web namespace.

Cookies are added to the Cookies collection of response object, the object which is responsible for keeping information to be rendered to browser. Example for writing and reading cookie

 //Create an instance of HttpCookie
Dim mycookie as new HttpCookie("userid")


 //Set parameters like value and expires
mycookie.Value = "1"
mycookie.Expires = DateTime.Now.AddMonths(1)

 //Add to the Cookies collection of response object
Response.Cookies.Add(mycookie)

 We can do same thing by directly setting values for Response.Cookies collection

Response.Cookies ("userid").value = "1"
Response.Cookies ("userid").Expires = DateTime.Now.AddMonths(1)

 The above code creates cookie and store it in user's drive for one month. The following code is used to retrieve a cookie later.

 Request object is used to send cookies information along with the request for page to server.

If Not Requet.Cookies("userid") Is Nothing Then
Dim a As String
a= Not Requet.Cookies("userid")
End If

Here first we are checking whether cookie exists or not because it can be deleted by user. Cookies won't work if user has disabled cookies in browser settings.


    



To check if the cookie is enabled or disabled on the client side we can use the following script on the first page of the application:

if ( Get_Cookie( 'test' ) )
{
document.write( 'cookies are currently enabled.' );
/*
this is an example of a set cookie variable, if
you want to use this on the page or on another script
instead of writing to the page you would just check that value
for true or false and then do what you need to do.
*/
cookie_set = true;
// and these are the parameters for Delete_Cookie:
// name, path, domain
// make sure you use the same parameters in Set and Delete Cookie.
Delete_Cookie('test', '/', '');
}
// if the Get_Cookie test fails, cookies
//are not enabled for this session.
else
{
document.write( 'cookies are not currently enabled.' );
cookie_set = false;
}


This would check if the cookie is enabled or not on the client browser.

Saturday, December 26, 2009

Master Pages in Asp.Net 3.5

Introduction

The introduction of Master Pages was one of the very innovative feature in Asp.Net 2.0. It helped a lot in reusing the design and common logic throughout the application which was earlier very tedious task. Further the updation and modification of existing code and design became very easy and manageable. This task was previously done with the help of user controls in which the user control was used to reuse the existing design + code but the updation and management was still an issue. With the introduction of Master Pages it was like a dream come true.


Asp.Net 3.5 went a step further and introduced the nested Master Pages which in reality made OOPS available to the design part as well. Here we could do all the things we can do on design part in OOPS that we could only do with a code. Now we will look at the way Master Pages are made and used.


Master pages allow you to create a consistent look and behavior for all the pages (or group of pages) in your web application.
A master page provides a template for other pages, with shared layout and functionality. The master page defines placeholders for the content, which can be overridden by content pages. The output result is a combination of the master page and the content page.
The content pages contains the content you want to display.
When users request the content page, ASP.NET merges the pages to produce output that combines the layout of the master page with the content of the content page.

Master Page Example

The master page above is a normal HTML page designed as a template for other pages.
The @ Master directive defines it as a master page.
The master page contains a placeholder tag for individual content.
The id="CPH1" attribute identifies the placeholder, allowing many placeholders in the same master page.
This master page was saved with the name "master1.master".
lamp Note: The master page can also contain code, allowing dynamic content.

Content Page Example


The content page above demonstrates how .NET controls can be inserted into the content page just like an into an ordinary page.




Nested Master Page Example

When one master page references another as its master, it is said to be a nested master page. A number of nested masters can be componentized into a single master. There is no architectural limitation to the number of child masters that can be created. This nested model is pretty cool and powerful, and allows arbitrary levels of nesting. The depth of nesting also does not impact on performance significantly. The advantage of this kind of structuring is that a number of child masters can be created to be subordinated to the overall look and feel of the site defined by the Parent master, while the child master give the child pages some uniqueness. While a parent master defines the overall layout of the pages—header, body and footer, the child master expands the body for a group of pages.
Just like the parent master page child masters have the extension .master too. It contains all the controls that are mapped to content place holders on the parent master page. The layout is similar to that of a content page in this respect. However, child masters also have content place holders of their own to display content of its child pages.
For example, you could define a top-level master-page called "MainMaster.master" that defines a common logo header and footer, and defines a content-placeholder for the page called "content". You could then define two sub-masters beneath it - one that provides a two-column layout model for the content ("TwoColumnMaster.master"), and one that provides a three-column layout model ("ThreeColumnMaster.master"). These two nested-master pages could then use the MainMaster.master file as the root master, and only adjust the layout within its content section (each would fill in the "content" placeholder and in turn add their own content-placeholders for sub-pages within it). The benefit of this approach is that if you ever want to change the logo or top-level design of the site, you only have to update one file (MainMaster.master) and then have every page on the site automatically pick it up regardless of what master file they were based on.
Note that different "contentplaceholders" on the main master can be used to load groups of content files loaded into the child masters which are in turn loaded into the main master. This implies that multiple child masters can load multiple content files into different "contentplaceholders" on the main master file.
ASP.NET 2.0 is not the first in support of "templating". However, the functionality provided by it goes beyond the frontiers of "templating" to make master pages components that can be reused. The mechanism is not based on class inheritance. The binding of the master and the content pages is defined statically and cannot be changed or set programmatically.
Below are a couple of sample codes which will help you in better understanding of the concept of Nested Master Pages and how to implement it?

Nested Master Pages - Example.

1. We have 2 master pages, "MainMaster.master" and "NestedMasterPage1.master".
2. "SubmasterPage.Master" is a child of "MainMaster.Master".
3. All .ASPX pages are inherited from "SubmasterPage.master".
As shown below:
Implementation Steps:
1. Below is the code for our MainMaster.master:
2. Add another Master page i.e. "NestedMasterPage1.master" from "Add New Item..."

3. Add Content page by right clicking the "SubMasterPage.Master" in solution explorer.

Now compile your application and view the result.    

Thus here we see that how the master pages work. By the use of Master Pages we can put the most common design and code in the main master page and according to requirement we can create sub-master pages or child master pages that would fulfill requirement of a set pages that need some common code.


Execution sequence of  events of master-content page

The execution sequence of events of master page and content page are as follows:

  1. Content page PreInit event.
  2. Master page controls Init event.
  3. Content controls Init event.
  4. Master page Init event.
  5. Content page Init event.
  6. Content page Load event.
  7. Master page Load event.
  8. Master page controls Load event.
  9. Content page controls Load event.
  10. Content page PreRender event.
  11. Master page PreRender event.
  12. Master page controls PreRender event.
  13. Content page controls PreRender event.
  14. Master page controls Unload event.
  15. Content page controls Unload event.
  16. Master page Unload event.
  17. Content page Unload event.

Wednesday, December 23, 2009

Validation Controls in Asp.Net

This tutorial gives a brief overview of how to use the ASP.NET Input Validation Controls.

Back when we had only ASP, developers who had to write webpages for forms knew that the most tedious part is writing code to validate the user input. User input had to be validated so that malicious use of the pages couldn't be achieve. User input had to be validated so that an incorrect piece of information would not be entered. User input had to be validated so that the information stored was standardized. Yeah, some people had libraries of ASP functions to validate common things such as postal codes (zip codes for you Americans), e-mail addresses, phone numbers, etc. The developers of ASP.NET saw the tedium in always having to check user input. They decided that to simplify our life by including validation controls.
ASP.NET validation controls also provide two ways of validation: Server-side or Client-side. The nice thing about these Validation controls is that it will preform client-side validation when it detects the browser is able (unless client-side validation has been disabled). Thus reducing roundtrips. And it will preform server-side where necessary. This client-side/server-side detection and validation is done without extra work by the developer!

With ASP.NET, there are six(6) controls included. They are:

  • The RequiredFieldValidation Control
  • The CompareValidator Control
  • The RangeValidator Control
  • The RegularExpressionValidator Control
  • The CustomValidator Control

Validator Control Basics
All of the validation controls inherit from the base class BaseValidator so they all have a series of properties and methods that are common to all validation controls. They are:

  • ControlToValidate - This value is which control the validator is applied to.
  • ErrorMessage - This is the error message that will be displayed in the validation summary.
  • IsValid - Boolean value for whether or not the control is valid.
  • Validate - Method to validate the input control and update the IsValid property.
  • Display - This controls how the error message is shown. Here are the possible options:
    • None (The validation message is never displayed.)
    • Static (Space for the validation message is allocated in the page layout.)
    • Dynamic (Space for the validation message is dynamically added to the page if validation fails.)



The RequiredFieldValidation Control
The first control we have is the RequiredFieldValidation Control. As it's obvious, it make sure that a user inputs a value. Here is how it's used:

Required field: <asp:textbox id="textbox1" runat="server"/>
<asp:RequiredFieldValidator id="valRequired" runat="server" ControlToValidate="textbox1"
    ErrorMessage="* You must enter a value into textbox1" Display="dynamic">*
asp:RequiredFieldValidator>
>

In this example, we have a textbox which will not be valid until the user types something in. Inside the validator tag, we have a single *. The text in the innerhtml will be shown in the controltovalidate if the control is not valid. It should be noted that the ErrorMessage attribute is not what is shown. The ErrorMessage tag is shown in the Validation Summary (see below).

The CompareValidator Control
Next we look at the CompareValidator Control. Usage of this CompareValidator is for confirming new passwords, checking if a departure date is before the arrival date, etc. We'll start of with a sample:

Textbox 1: <asp:textbox id="textbox1" runat="server"/><br />
Textbox 2: <asp:textbox id="textbox2" runat="server"/><br />
<asp:CompareValidator id="valCompare" runat="server"
    ControlToValidate="textbox1" ControlToCompare="textbox2"
    Operator="Equals"
    ErrorMessage="* You must enter the same values into textbox 1 and textbox 2"
    Display="dynamic">*
asp:CompareValidator>
>

Here we have a sample where the two textboxes must be equal. The tags that are unique to this control is the ControlToCompare attribute which is the control that will be compared. The two controls are compared with the type of comparison specified in the Operator attribute. The Operator attribute can contain Equal, GreterThan, LessThanOrEqual, etc.
Another usage of the ComapareValidator is to have a control compare to a value. For example:

Field: <asp:textbox id="textbox1" runat="server"/>
<asp:CompareValidator id="valRequired" runat="server" ControlToValidate="textbox1"
    ValueToCompare="50"
    Type="Integer"
    Operator="GreaterThan"
    ErrorMessage="* You must enter the a number greater than 50" Display="dynamic">*
asp:CompareValidator>
>

The data type can be one of: Currency, Double, Date, Integer or String. String being the default data type.

The RangeValidator Control
Range validator control is another validator control which checks to see if a control value is within a valid range. The attributes that are necessary to this control are: MaximumValue, MinimumValue, and Type.
Sample:

Enter a date from 1998:
<asp:textbox id="textbox1" runat="server"/>
<asp:RangeValidator id="valRange" runat="server"
    ControlToValidate="textbox1"
    MaximumValue="12/31/1998"
    MinimumValue="1/1/1998"
    Type="Date"
    ErrorMessage="* The date must be between 1/1/1998 and 12/13/1998" Display="static">*asp:RangeValidator>
>


The RegularExpressionValidator Control
The regular expression validator is one of the more powerful features of ASP.NET. Everyone loves regular expressions. Especially when you write those really big nasty ones... and then a few days later, look at it and say to yourself. What does this do?
Again, the simple usage is:

E-mail: <asp:textbox id="textbox1" runat="server"/>
<asp:RegularExpressionValidator id="valRegEx" runat="server"
    ControlToValidate="textbox1"
    ValidationExpression=".*@.*\..*"
    ErrorMessage="* Your entry is not a valid e-mail address."
    display="dynamic">*
asp:RegularExpressionValidator>
>

Here is a webpage I like to use to check my regular expressions.

The CustomValidator Control
The final control we have included in ASP.NET is one that adds great flexibility to our validation abilities. We have a custom validator where we get to write out own functions and pass the control value to this function.

Field: <asp:textbox id="textbox1" runat="server">
<asp:CustomValidator id="valCustom" runat="server"
    ControlToValidate="textbox1"
    ClientValidationFunction="ClientValidate"
    OnServerValidate="ServerValidate"
    ErrorMessage="*This box is not valid" dispaly="dynamic">*
asp:CustomValidator>
>

We notice that there are two new attributes ClientValidationFunction and OnServerValidate. These are the tell the validation control which functions to pass the controltovalidate value to. ClientValidationFunction is usually a javascript funtion included in the html to the user. OnServerValidate is the function that is server-side to check for validation if client does not support client-side validation.
Client Validation function:


&ltscript language="Javascript">

>

Server Validation function:


Sub ServerValidate (objSource As Object, objArgs As ServerValidateEventsArgs)
    ' Code goes here
End Sub
b


Validation Summary
ASP.NET has provided an additional control that complements the validator controls. This is the validation summary control which is used like:

<asp:ValidationSummary id="valSummary" runat="server"
    HeaderText="Errors:"
    ShowSummary="true" DisplayMode="List" />
>

The validation summary control will collect all the error messages of all the non-valid controls and put them in a tidy list. The list can be either shown on the web page (as shown in the example above) or with a popup box (by specifying ShowMessageBox="True")

Now you know how to use the Validator Controls in ASP.NET! Have fun!
I will also upload a sample of all the validator controls to the code sample section.

Acknoledgment: Professional ASP.NET (published by Wrox) was used a reference. It's a good book!

Tips to remember

  • If you are doing server-side validation, make sure the button onclick method has a Page.IsValid if statement or it will look like your validators aren't doing anything
  • Don't forget to wrap everything in the <form runat=server> tag.

Tuesday, December 22, 2009

Validation Controls in Asp.Net --- Tips



Recently I needed to disable some ASP.NET RequiredFieldValidator controls on one page depending on user input.
This is trivial you say. But the problem was that this needed to occur instantly on Client Side based on the state of one CheckBox control and not after a full page PostBack.
For example imagine you have TextBox control that needs to be filled by user only if one CheckBox control on the page is checked.
So normally, you would add RequiredFieldValidator to the page, wire it up with that TextBox control, and enable/disable this Validator on PageLoad event depending on the Checked state of the CheckBox.
But let us consider this rare situation: User checks the CheckBox, without filling the TextBox and submits the page. On PageLoad the RequiredFieldValidator gets activated, and page is presented to the user again with validation error.
User changes his mind and makes Checkbox unchecked (he does not want to fill the TextBox) and tries to submit the form, but what happens?
Client Side validation of RequiredFieldValidator is triggered to enforce user to fill that TextBox and user cannot submit the page.
The only solution is to Enable/Disable the ASP.NET Validator controls on page with JavaScript code as soon as user changes the Checked state of the CheckBox control on the page.
After some digging I found out that ASP.NET Validator controls have Client Side API that supports some niffty features, so here is the list of supported Client Side functions:

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.
 NOTE:
One thing is important to say here: Server Side Validation will occur after page PostBack even if you programmatically disable Client Side validation with Java Script.
This API just allows you to manipulate the Client Side state of your Validator controls, Disable or Enable them and therefore allow or forbid the user to submit the page, and all this does not affect how this Server Side Validators will behave on Server Side.
So how we use that API?

Let us set up a simple example project with two TextBox controls (Full Name and Email) with RequiredFieldValidators for both of them and RegularExpressionValidator for Email field and a CheckBox control that Enables/Disables the Client Side validation for all the Validator controls.

Here is how our ASPX page code looks like:

<body onload="InitValidators();">
    <form id="form1" runat="server">
    <div>
        <asp:CheckBox ID="enableValidatorsCheckBox" runat="server" Text="Validators Enabled - Click on this checkbox to Enable/Disable client side validation for ASP.NET Validator controls." Checked="true" onclick="ValidatorsEnabled(this.checked);" />
        <br /><br />
        <asp:Label ID="Label1" runat="server" Text="Full Name">asp:Label> 
        <asp:TextBox ID="Name" runat="server">asp:TextBox>
        <asp:RequiredFieldValidator ID="NameRequiredFieldValidator" runat="server" ControlToValidate="Name"
            ErrorMessage="Please enter your full name">asp:RequiredFieldValidator>
        <br />
        <asp:Label ID="Label2" runat="server" Text="Email">asp:Label>        
        <asp:TextBox ID="Email" runat="server">asp:TextBox>
        <asp:RequiredFieldValidator ID="EmailRequiredFieldValidator" runat="server" ControlToValidate="Email"
        ErrorMessage="Please enter your email address.">asp:RequiredFieldValidator>
        <asp:RegularExpressionValidator ID="EmailRegexValidator" runat="server"  ControlToValidate="Email"
        ErrorMessage="Invalid Email" ValidationExpression=".*@.{2,}\..{2,}">asp:RegularExpressionValidator>
        <br /><br />
        <asp:Button ID="SubmitButton" runat="server" Text="Submit" /> 
        <br /><br />
        <asp:Label ID="MessagesLabel" runat="server" Text="">asp:Label> <br />
        <br />
        <asp:ValidationSummary ID="ValidationSummaryControl" runat="server"
            HeaderText="Validation Errors:" />
    div>
    form>
    <script type="text/javascript" language="javascript">
        function InitValidators()
        {
            // retrieve instance of our checkbox
            var checkbox = document.getElementById('<%=enableValidatorsCheckBox.ClientID%>');
            // enable/disable all validators on page based on checkbox state
            ValidatorsEnabled(checkbox.checked);
        }

        function ValidatorsEnabled(state)
        {
            ValidatorEnable(document.getElementById('<%=NameRequiredFieldValidator.ClientID%>'), state);
           ValidatorEnable(document.getElementById('<%=EmailRequiredFieldValidator.ClientID%>'), state);                                 
            ValidatorEnable(document.getElementById('<%=EmailRegexValidator.ClientID%>'), state);         
        }
    script>
body>


So as you can see from the code we have created a simple helper Java Script function ValidatorsEnabled(state) to enable/disable all validator controls on the page depending on the state parameter supplied.

On each page load (using the body onload Client Side event) we call the InitValidators() function that just takes the Checked state of the CheckBox control and calls the ValidatorsEnabled with that value so that Client Side validation is enabled/disabled on page load.
Also whenever user clicks on the CheckBox control (using the onclick Client Side event) we call the ValidatorsEnabled function also supplying the state of the CheckBox as state parameter to Enable/Disable Client Side validation.
Note: we are using Server Side tags in our JavaScript code: '<%=NameRequiredFieldValidator.ClientID%>' to dynamically retrieve the Client Side names of our Server Side Validators so we don't have to hard code them, and therefore have to change them in Java Script code if we change their names on Server Side.

And here is what happens at our code behind:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (Page.IsPostBack)
        {
            Page.Validate();
            StringBuilder msg = new StringBuilder("Page Is Submitted. Validation State: ");

            if (Page.IsValid)
            {
                msg.AppendFormat("Valid. Submitted Name: {0}  Submitted Email: {1}", Name.Text, Email.Text);
            }
            else
            {
                msg.Append("INVALID!");
            }

            MessagesLabel.Text = msg.ToString();
        }
    }

Simple stuff here, we just trigger the page Validation if there is a PostBack and display status messages in the Label control depending on the validation status of the page/validation controls.
So let us see what happens if we run the sample page? Initially Client Side validation is enabled for all our Validator controls and until we fill the required data we cannot submit the page:



If you try to submit this page Post Back will not occur because Client Side validation will get triggered.
Here is the result, page is not submitted, instead an error message is displayed in each Validator control and in Validation Summary control on the bottom of the page:



Now, if you click on the CheckBox on top and uncheck it, the Client Side validation for all our Validator controls will be instantly disabled by calling our Java Script function ValidatorsEnabled(false) and all the validation errors will at once dissapear!
You will be permitted to submit the page, even if you dont fill in the required information, full page PostBack will happen and on the Server Side validation will get triggered for each Validator control.

Good side of this is that you can override the Validators behaviour on Client Side and allow the Post Back to occur and then decide on Server Side if you really want to disable some of the Validator Controls or display error messages, enforce custom business logic etc.

Here is how the page looks after you have disabled Client Side validation and submitted it without filling all the required data:

 
TIP:
Always make sure you have a really good reason to do all this because generally Client Side validation is a good thing and should be enabled by default and used whenever possible because it saves bandwidth and forbids unnecessary postbacks.

Control is now in your hands, so use it wisely :)

LinkWithin

Related Posts with Thumbnails