Validating Server Side using the Validation Callout Extender with the Custom Validator
Technologies Used: ASP.Net 2.0, Ajax.Net 1.0, C# 2.0
The Problem:
You want to do a custom validation on the server using the Ajax control kit's Validation Callout Extender
and the CustomValidator server control. The problem is that the ValidationCalloutExtender does not currently support
the CustomValidator's call to the OnServerValidate functionality. The only thing supported by the Validation Callout Extender
at the time of this writing is the call to a client function from the Custom Validator, using the ClientValidationFunction.
The Solution:
In short these are the steps that should happen. We will still call the ClientValidationFunction of the
CustomValidator. From the client function (JavaScript function), we will call a server side method
passing the value of that we are trying to custom validate. Then we will pass back a value
from the server method to a client function, JavaScript again, denoting if the validation passed or failed.
1. Drag a ScriptManager and UpdatePanel into a webform. Now drop a TextBox, Button, CustomValidator, and a
ValidatorCalloutExtender inside the UpdatePanel as shown below. Take note of the "ValidateTextBox", this is
the JavaScript function that will be called client side.
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server" /><br />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<asp:CustomValidator ID="CustomValidator1"
ControlToValidate="TextBox1" Display="None" runat="server"
ErrorMessage="<b>Invalid Textbox Value</b><br/><br/>This
is the text in your Validator Callout Extender error.<br/>"
ClientValidationFunction="ValidateTextBox" />
<cc1:ValidatorCalloutExtender ID="ValidatorCalloutExtender1"
TargetControlID="CustomValidator1" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
2. Write the client-side function that will be called by the CustomValidator. This function will be calling back a
Server Method called "YourCallBackMethod" passing in the value of the TextBox.
var resultOfTheCallBack;
function ValidateTextBox(sender, args)
{
var textBoxValue
= document.getElementById('TextBox1').value;
// call server callback method passing
the value in your textbox
YourCallBackMethod(textBoxValue);
if(resultOfTheCallBack
== 'Valid')
args.IsValid = true;
else
args.IsValid = false;
}
3. In the Page Load event of the code file create a reference to the call back method, and set the reference inside a
Client Script by registering the script block.
string callBackReference = Page.ClientScript.GetCallbackEventReference(this,
"arg", "CallBackEventReference", "context");
string yourCallBackScript =
"function YourCallBackMethod(arg, context) { " + callBackReference
+ "; }";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "YourCallBackMethod", yourCallBackScript, true);
4. Implement the ICallBackEventHandler.
public partial
class TestPage : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
This is the main juice of this code. The member methods of the ICallBackEventHandler
is where we will be doing the validation and then returning a string as to the result of the validation. In simple terms,
the RaiseCallbackEvent is called by the client-side function call "YourCallBackMethod(textBoxValue);". The call is possible
because on #3 above, we registered a script that has a reference to this call back method. You will also notice that the
textBoxValue is caught by the "eventArgument" parameter of the RaiseCallbackEvent method. From here we can set the value of
a class-wide variable that we declared called "_callBackStatus" to either pass or failed, success or failed, or whatever you like. You
can think of this function as the setter method.
Note: You can pass multiple values from the calling client-side function "YourCallBackMethod" to the "RaiseCallbackEvent"
on the server. For example from the client-side function:
YourCallBackMethod(param1Value, param2Value, param3Value);
On the server, the RaiseCallbackEvent method remains the same. However, the value of the "eventArgument"
now have a Comma-delimited values of the passed parameters. Going back to the code, here's what the
ICallbackEventHandler's implementation looks like.
// ICallbackEventHandler Members
public string GetCallbackResult()
{
return _callBackStatus;
}
public void RaiseCallbackEvent(string eventArgument)
{
// do your validation coding here
if (eventArgument
== "junnark")
_callBackStatus =
"Valid";
}
The "GetCallbackResult()" method does exactly what it sound like, it gets the result
back to the call back reference method that we set up in the page load event. The client-side function that the GetCallbackResult
method will call is the "CallBackEventReference", which is referenced at the page load event. In this client-side function, we can
now set the result of the Server-side validation call.
function CallBackEventReference(result,
context)
{
resultOfTheCallBack = result;
}
See it in Action:
Click Here to see it in action.
First enter any text in the TextBox, then click the button. Notice
that the ValidatorCallout error shows up. Now enter the text "junnark" in the TextBox and then click the button, the
error goes away because the the validation is now valid. Note: The textbox will not be validated if no text is entered,
because the validation does not require any text.
The Complete Code:
<%@
Page
Language="C#"
AutoEventWireup="true" CodeBehind="TestPage.aspx.cs" Inherits="TestPage" %>
<%@
Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<%@
Register Assembly="System.Web.Extensions,
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI" TagPrefix="asp" %>
<!DOCTYPE
html
PUBLIC "-//W3C//DTD
XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml" >
<head
runat="server">
<title>Using ValidatorCallout Extender with a CustomValidator
Control</title>
<script language="javascript" type="text/javascript">
var resultOfTheCallBack;
function ValidateTextBox(sender,
args)
{
var textBoxValue = document.getElementById('TextBox1').value;
// call server callback
method passing the value in your textbox
YourCallBackMethod(textBoxValue);
if(resultOfTheCallBack ==
'Valid')
args.IsValid = true;
else
args.IsValid = false;
}
function CallBackEventReference(result,
context)
{
resultOfTheCallBack = result;
}
</script>
</head>
<body>
<form
id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel
ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server" /><br />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<asp:CustomValidator ID="CustomValidator1"
ControlToValidate="TextBox1" Display="None" runat="server"
ErrorMessage="<b>Invalid
Textbox Value</b><br/><br/>This is the text in your Validator
Callout Extender error.<br/>"
ClientValidationFunction="ValidateTextBox" />
<cc1:ValidatorCalloutExtender ID="ValidatorCalloutExtender1"
TargetControlID="CustomValidator1" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Here's the code file:
using System;
public partial
class TestPage : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
{
private
string _callBackStatus =
null;
protected
void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// create a call back
reference method and then
string
callBackReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "CallBackEventReference", "context");
string
yourCallBackScript = "function YourCallBackMethod(arg,
context) { " + callBackReference +
"; }";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "YourCallBackMethod", yourCallBackScript,
true);
}
}
protected
void Button1_Click(object sender, EventArgs e)
{
}
// ICallbackEventHandler Members
public
string GetCallbackResult()
{
return _callBackStatus;
}
public
void RaiseCallbackEvent(string eventArgument)
{
// do your validation
coding here
if (eventArgument == "junnark")
_callBackStatus =
"Valid";
}
}
Happy Coding!!!
Date Modified: August 8, 2007