Archive

Posts Tagged ‘AJAX’

Creating AJAX Validator Control

May 25, 2008 5 comments

Imagine that you are creating a website registration form and you need to validate a Login ID or Email field. You want to make sure that the Login ID or Email entered does not already exist in the database. You could use the CustomValidator control to call a server-side function to check whether the field is unique in the database.

<asp:TextBox id="txtEmail" Runat="server" /> <asp:CustomValidator id="valEmail" ControlToValidate="txtEmail" Text="Email already exists" OnServerValidate="valEmail_ServerValidate" Runat="server" />
void valEmail_ServerValidate(Object source, ServerValidateEventArgs args) { if (EmailAlreadyExists(args.Value)) args.IsValid = false; else args.IsValid = true; }

This of course causes a postback to the server where the server-side function is executed and the page is refreshed. This can be frustrating to the user to have to enter all the fields and submit and the page refreshes only to find out that the Email address is already in the system.

To provide a better user experience we somehow need to call the server-side function from the client without causing a postback. Using AJAX (Asynchronous JavaScript and XML) we can create a validator control to call the server-side validation function from the client. The advantage of using AJAX is that no postback to the server is apparent to the user.

Our control needs to inherit from the BaseValidator class and also implement the ICallbackEventHandler interface. The BaseValidator class serves as the abstract base class for validation controls and provides the core implementation for all validation controls. The BaseValidator requires you to implement a single method:

  • EvaluateIsValid – returns true when the form field being validated is valid.

The BaseValidator class also includes several other methods that you can override or otherwise use. The most useful of these methods is the following:

  • GetControlValidationValue – enables you to retrieve the value of the control being validated.

When you create a custom validation control, you override the EvaluateIsValid() method and, within the EvaluateIsValid() method, you call GetControlValidationValue to get the value of the form field being validated.

public class MyAjaxValidator : BaseValidator, ICallbackEventHandler { public event ServerValidateEventHandler ServerValidate; string _controlToValidateValue; protected override bool EvaluateIsValid() { string controlToValidateValue = this.GetControlValidationValue(this.ControlToValidate); return ExecuteValidationFunction(controlToValidateValue); } private bool ExecuteValidationFunction(String controlToValidateValue) { ServerValidateEventArgs args = new ServerValidateEventArgs(controlToValidateValue, this.IsValid); if (ServerValidate != null) ServerValidate(this, args); return args.IsValid; }

The ICallbackEventHandler interface defines two methods that are called on the server when an AJAX request is made from the client:

  • RaiseCallbackEvent – called to handle the event, passing the event argument as a parameter
  • GetCallbackResult – returns the result of the callback
public void RaiseCallbackEvent(string eventArgument) { _controlToValidateValue = eventArgument; } public string GetCallbackResult() { return ExecuteValidationFunction(_controlToValidateValue).ToString(); }

In the OnPreRender() method, a JavaScript include file and startup script are registered.

protected override void OnPreRender(EventArgs e) { String eventRef = Page.ClientScript.GetCallbackEventReference(this, "", "", ""); String includeScript = Page.ResolveClientUrl("~/Scripts/MyAjaxValidator.js"); Page.ClientScript.RegisterClientScriptInclude("MyAjaxValidator", includeScript); String startupScript = String.Format(“document.getElementById('{0}').evaluationfunction = 'MyAjaxValidatorEvaluateIsValid';", this.ClientID); Page.ClientScript.RegisterStartupScript(this.GetType(), "MyAjaxValidator", startupScript, true); base.OnPreRender(e); } protected override bool DetermineRenderUplevel() { return Context.Request.Browser.SupportsCallback; }

The JavaScript include file contains the client-side functions that are called when the MyAjaxValidator validates a form field on the client. The startup script associates the client-side MyAjaxValidatorEvaluateIsValid() function with the MyAjaxValidator control. The client-side validation framework automatically calls this JavaScript function when performing validation.

function MyAjaxValidatorEvaluateIsValid(val) { var value = ValidatorGetValue(val.controltovalidate); WebForm_DoCallback(val.id, value, MyAjaxValidatorResult, val, MyAjaxValidatorError, true); return true; } function MyAjaxValidatorResult(returnValue, context) { if (returnValue == 'True') context.isvalid = true; else context.isvalid = false; ValidatorUpdateDisplay(context); } function MyAjaxValidatorError(message) { alert('Error: ' + message); }

The MyAjaxValidatorEvaluateIsValid() JavaScript method initiates an AJAX call by calling the WebForm_DoCallback() method. This method calls the server-side validation function associated with the MyAjaxValidator control. When the AJAX call completes, the MyAjaxValidatorResult() method is called. This method updates the display of the validation control on the client.

The following page illustrates how you can use the MyAjaxValidator control. This page handles the MyAjaxValidator control’s ServerValidate event to associate a custom validation function with the control. The validation function checks whether a email already exists in the database. If you enter a email that already exists, a validation error message is displayed. The message is displayed in the browser before you submit the form back to the server.

<form id="form1" runat="server"> <asp:Label id="lbEmail" Text="Email:" AssociatedControlID="txtEmail" Runat="server" /> <asp:TextBox id="txtEmail" Runat="server" /> <custom:MyAjaxValidator id="valEmail" ControlToValidate="txtEmial" Text="Email already exists" OnServerValidate="valEmail_ServerValidate" Runat="server" /> <br /> <!--some other controls here --> <br /> <asp:Button id="btnSubmit" Text="Submit" Runat="server" OnClick="btnSubmit_Click" /> </form>

And in code behind

protected void valEmail_ServerValidate(object source, ServerValidateEventArgs args) { if (EmailAlreadyExists(args.Value)) args.IsValid = false; else args.IsValid = true; }

It is important to realize that you can associate any server-side validation function with the MyAjaxValidator. You can perform a database lookup, call a web service, or perform a complex mathematical function. Whatever function you define on the server is automatically called on the client.

Complete code for MyAjaxValidator:

public class MyAjaxValidator : BaseValidator, ICallbackEventHandler { public event ServerValidateEventHandler ServerValidate; string _controlToValidateValue; protected override bool EvaluateIsValid() { string controlToValidateValue = this.GetControlValidationValue(this.ControlToValidate); return ExecuteValidationFunction(controlToValidateValue); } protected override void OnPreRender(EventArgs e) { String eventRef = Page.ClientScript.GetCallbackEventReference(this, "", "", ""); String includeScript = Page.ResolveClientUrl("~/Scripts/MyAjaxValidator.js"); Page.ClientScript.RegisterClientScriptInclude("MyAjaxValidator", includeScript); String startupScript = String.Format(“document.getElementById('{0}').evaluationfunction = 'MyAjaxValidatorEvaluateIsValid';", this.ClientID); Page.ClientScript.RegisterStartupScript(this.GetType(), "MyAjaxValidator", startupScript, true); base.OnPreRender(e); } protected override bool DetermineRenderUplevel() { return Context.Request.Browser.SupportsCallback; } public void RaiseCallbackEvent(string eventArgument) { _controlToValidateValue = eventArgument; } public string GetCallbackResult() { return ExecuteValidationFunction(_controlToValidateValue).ToString(); } private bool ExecuteValidationFunction(String controlToValidateValue) { ServerValidateEventArgs args = new ServerValidateEventArgs(controlToValidateValue, this.IsValid); if (ServerValidate != null) ServerValidate(this, args); return args.IsValid; } }
 
REF:
Sams ASP.Net 2.0 by Stephen Walther
 

Tags: , ,