Preferred Language:

Listing 3.22 - AjaxValidator.cs, Listing 3.23 - AjaxValidator.js, Listing 3.24 - ShowAjaxValidator.aspx

Illustrates how you can create a custom validation control that uses Ajax to execute a custom server-side validation function.

Listing 3.22 - AjaxValidator.cs (C#)
Copy

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace myControls
{
    /// <summary>
    /// Enables you to perform custom validation on both the client and server
    /// </summary>
    public class AjaxValidator : BaseValidator, ICallbackEventHandler
    {
        public event ServerValidateEventHandler ServerValidate;

        private string _controlToValidateValue;

        protected override void OnPreRender(EventArgs e)
        {
            string eventRef = Page.ClientScript.GetCallbackEventReference(this, "", "", "");

            // Register include file
            string includeScript = Page.ResolveClientUrl("~/ClientScripts/AjaxValidator.js");
            Page.ClientScript.RegisterClientScriptInclude("AjaxValidator", includeScript);

            // Register startup script
            string startupScript = String.Format("document.getElementById('{0}').evaluationfunction = 'AjaxValidatorEvaluateIsValid';", this.ClientID);
            Page.ClientScript.RegisterStartupScript(this.GetType(), "AjaxValidator", startupScript, true);

            base.OnPreRender(e);
        }

        /// <summary>
        /// Only do the AJAX on browsers that support it
        /// </summary>
        protected override bool DetermineRenderUplevel()
        {
            return Context.Request.Browser.SupportsCallback;
        }

        /// <summary>
        /// Server method called by client AJAX call
        /// </summary>
        public string GetCallbackResult()
        {
            return ExecuteValidationFunction(_controlToValidateValue).ToString();
        }

        /// <summary>
        /// Return callback result to client
        /// </summary>
        public void RaiseCallbackEvent(string eventArgument)
        {
            _controlToValidateValue = eventArgument;
        }

        /// <summary>
        /// Server-side method for validation
        /// </summary>
        protected override bool EvaluateIsValid()
        {
            string controlToValidateValue = this.GetControlValidationValue(this.ControlToValidate);
            return ExecuteValidationFunction(controlToValidateValue);
        }

        /// <summary>
        /// Performs the validation for both server and client
        /// </summary>
        private bool ExecuteValidationFunction(string controlToValidateValue)
        {
            ServerValidateEventArgs args = new ServerValidateEventArgs(controlToValidateValue, this.IsValid);
            ServerValidate(this, args);
            return args.IsValid;
        }

    }
}

The AjaxValidator uses the client-side JavaScript file below.

Listing 3.23 - AjaxValidator.js
Copy

// Performs AJAX call back to server
function AjaxValidatorEvaluateIsValid(val)
{
    var value = ValidatorGetValue(val.controltovalidate);
    WebForm_DoCallback(val.id, value, AjaxValidatorResult, val, AjaxValidatorError, true); 
    return true;
}

// Called when result is returned from server
function AjaxValidatorResult(returnValue, context)
{
    if (returnValue == 'True')
        context.isvalid = true;
    else
        context.isvalid = false;
    ValidatorUpdateDisplay(context);
}

// If there is an error, show it
function AjaxValidatorError(message)
{
    alert('Error: ' + message);
}

The following page uses the AjaxValidator control. The code here has been modified slightly from the book so that it does not use a database. If you enter the name Bob into the TextBox, the AjaxValidator will display an error message when you tab away from the field. The validation logic executes on the server and displays the error on the browser.

Listing 3.24 - ShowAjaxValidator.aspx (C#)
Copy | Try This Code!

<%@ Page Language="C#" %>
<%@ Register TagPrefix="custom" Namespace="myControls" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Web.Configuration" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

    /// <summary>
    /// Validation function that is called on both the client and server
    /// </summary>
    protected void AjaxValidator1_ServerValidate(object source, ServerValidateEventArgs args)
    {
        if (UserNameExists(args.Value))
            args.IsValid = false;
        else
            args.IsValid = true;
    }
    
    /// <summary>
    /// Returns true when user name already exists
    /// in Users database table
    /// </summary>
    private bool UserNameExists(string userName)
    {
        return (userName.ToLower() == "bob");
        
        //string conString = WebConfigurationManager.ConnectionStrings["UsersDB"].ConnectionString;
        //SqlConnection con = new SqlConnection(conString);
        //SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM Users WHERE UserName=@UserName", con);
        //cmd.Parameters.AddWithValue("@UserName", userName);
        //bool result = false;
        //using (con)
        //{
        //    con.Open();
        //    int count = (int)cmd.ExecuteScalar();
        //    if (count > 0)
        //        result = true;
        //}
        //return result;
    }

    /// <summary>
    /// Insert new user name to Users database table
    /// </summary>
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        //string conString = WebConfigurationManager.ConnectionStrings["UsersDB"].ConnectionString;
        //SqlConnection con = new SqlConnection(conString);
        //SqlCommand cmd = new SqlCommand("INSERT Users (UserName,FavoriteColor) VALUES (@UserName,@FavoriteColor)", con);
        //cmd.Parameters.AddWithValue("@UserName", txtUserName.Text);
        //cmd.Parameters.AddWithValue("@FavoriteColor", txtFavoriteColor.Text);
        //using (con)
        //{
        //    con.Open();
        //    cmd.ExecuteNonQuery();
        //}
        //txtUserName.Text = String.Empty;
        //txtFavoriteColor.Text = String.Empty;
    }
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Show AjaxValidator</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
    <asp:Label
        id="lblUserName"
        Text="User Name:"
        AssociatedControlID="txtUserName"
        Runat="server" />
    <asp:TextBox
        id="txtUserName"
        Runat="server" />
    <custom:AjaxValidator
        id="AjaxValidator1"
        ControlToValidate="txtUserName"
        Text="User name already taken!"
        OnServerValidate="AjaxValidator1_ServerValidate" 
        Runat="server" />
    
    <br /><br />
    <asp:Label
        id="lblFavoriteColor"
        Text="Favorite Color:"
        AssociatedControlID="txtFavoriteColor"
        Runat="server" />
    <asp:TextBox
        id="txtFavoriteColor"
        Runat="server" />

    <br /><br />
    <asp:Button
        id="btnSubmit"
        Text="Submit"
        Runat="server" OnClick="btnSubmit_Click" />
    
    </div>
    </form>
</body>
</html>