接上篇 创建自定义验证控件(1)
开发环境VS2008+SQL2005
本篇将写一个比较复杂的自定义控件,AjaxValidator(AJAX自定义验证控件)。AjaxValidator控件用于创建一个服务器端的自定义验证函数。AjaxValidator可以在浏览器调用自定义的验证方法(即客户端脚本直接调用服务器端方法)。
AjaxValidator控件使用AJAX从客户端调用服务器端验证方法,使用AJAX优势在于用户不用显示地回传服务器端。
大家在创建一个注册表单,并且需要验证用户名字段,以确认用户输入的用户名在数据库中并不存在。本篇就利用AjaxValidator写了一个这样的DEMO。AjaxValidator控件可以在客户端调用服务端的验证方法来检查用户名在数据库中是否唯一。
AjaxValidator类的代码如下
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
//引用上述2个命名空间
namespace validatorControls
{
/// <summary>
///AjaxValidator 的摘要说明
///可以让你自定义对客户端和服务端的验证
///by mFrog
///2008 12,4
/// </summary>
public class AjaxValidator : BaseValidator, ICallbackEventHandler
{
public AjaxValidator()
{
//
//TODO: 在此处添加构造函数逻辑
//
}
//定一个ServerValidateEventHandler委托的事件
public event ServerValidateEventHandler ServerValidate;
string _controlToValidateValue;
protected override void OnPreRender(EventArgs e)
{
String evenRef = Page.ClientScript.GetCallbackEventReference(this, "", "", "");
//注册要导入的脚本文件
String includeScript = Page.ResolveClientUrl("~/ClientScripts/AjaxValidator.js");
Page.ClientScript.RegisterClientScriptInclude("AjaxValidator", includeScript);
//注册启动脚本
String startupScript = String.Format("document.getElementById('{0}').evaluationfunction = 'AjaxValidatorEvaluateIsValid';", this.ClientID);
Page.ClientScript.RegisterStartupScript(this.GetType(), "AjaxValidator", startupScript, true);
base.OnPreRender(e);
}
/// <summary>
///浏览器对AJAX技术的支持
/// </summary>
protected override bool DetermineRenderUplevel()
{
return Context.Request.Browser.SupportsCallback;
}
/// <summary>
/// 客户端ajax调用服务器端方法
/// </summary>
/// <returns></returns>
public string GetCallbackResult()
{
return ExecuteValidationFunction(_controlToValidateValue).ToString();
}
/// <summary>
/// 回调返回结果到客户端
/// </summary>
/// <param name="eventArgument"></param>
public void RaiseCallbackEvent(string eventArgument)
{
_controlToValidateValue = eventArgument;
}
/// <summary>
/// 服务器端的方法验证
/// </summary>
/// <returns></returns>
protected override bool EvaluateIsValid()
{
String controlToValidateValue = this.GetControlValidationValue(this.ControlToValidate);
return ExecuteValidationFunction(controlToValidateValue);
}
/// <summary>
/// 在服务器端和客户端都执行验证
/// </summary>
/// <param name="controlToValidateValue"></param>
/// <returns></returns>
private bool ExecuteValidationFunction(String controlToValidateValue)
{
ServerValidateEventArgs args = new ServerValidateEventArgs(controlToValidateValue,this.IsValid);
if (ServerValidate != null)
{
ServerValidate(this,args);
}
return args.IsValid;
}
}
}
AjaxValidato控件继承BaseValidator,并实现了ICallbackEventHandler接口。ICallbackEventHandler接口定义了两个方法,当客户端发出AJAX请求时,这两个方法在服务器端调用。
在OnPreRender()方法中,注册了一个内嵌JAVASCRIPT文件和启动脚本。内嵌JAVASCRIPT文件包含了AjaxValidato控件在客户端验证表单字段时调用的客户端函数。启动脚本把客户端的AjaxValidatorEvaluateIsValid()方法和AjaxValidato控件关联起来。执行验证时,客户端验证框架自动调用这个JAVASCRIPT方法。
下面是AjaxValidato控件使用的JAVASCRIPT方法
Code
//AJAX请求执行回服务器
function AjaxValidatorEvaluateIsValid(val) {
var value = ValidatorGetValue(val.controltovalidate);
WebForm_DoCallback(val.id, value, AjaxValidatorResult, val, AjaxValidatorError, true);
return true;
}
//从服务器返回结果
function AjaxValidatorResult(returnValue, context) {
if (returnValue == 'True')
{
context.isvalid = true;
}
else
{
context.isvalid = false;
}
ValidatorUpdateDisplay(context);
}
//显示错误
function AjaxValidatorError(message)
{
alert('Error:'+message);
}
JAVASCRIPT方法AjaxValidatorEvaluateIsValid()通过调用WebForm_DoCallback()方法初始化一个AJAX调用。该方法调用AjaxValidator控件关联的服务器端验证方法。当AJAX调用完成时,再调用AjaxValidatorResult()方法。这个方法在客户端更新验证控件的显示。
页面代码:
Code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register TagPrefix="mFrog" Namespace="validatorControls" %>
<!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>AjaxValidatorDEMO</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblUserName" runat="server" AssociatedControlID="txtUserName">用户名</asp:Label>
<asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
<mFrog:AjaxValidator ID="avUserName" ControlToValidate="txtUserName"
runat="server" Text="此用户名已经存在"
onservervalidate="avUserName_ServerValidate" Display="Dynamic"></mFrog:AjaxValidator>
<asp:RequiredFieldValidator ID="rfvUserName" runat="server"
ControlToValidate="txtUserName" Display="Dynamic" ErrorMessage="用户名不能为空"></asp:RequiredFieldValidator>
<br />
<br />
<asp:Label ID="Label1" runat="server" Text="密码"></asp:Label>
<asp:TextBox ID="txtUserPwd" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvUserPwd" runat="server"
ControlToValidate="txtUserPwd" ErrorMessage="密码不能为空"></asp:RequiredFieldValidator>
<br />
<br />
<asp:Button ID="btnSubmit" runat="server" Text="提交" onclick="btnSubmit_Click" />
</div>
</form>
</body>
</html>
后台CS代码:
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Web.Configuration;
public partial class _Default : System.Web.UI.Page
{
/// <summary>
/// 返回true时,用户名已存在
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
private bool UserNameExists(string username)
{
string conString= WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
string selectString="select count(*) from User_Info where UserName=@UserName";
SqlConnection conn = new SqlConnection(conString);
SqlCommand cmd = new SqlCommand(selectString, conn);
cmd.Parameters.AddWithValue("@UserName", username);
bool result = false;
using (conn)
{
conn.Open();
int count = (int)cmd.ExecuteScalar();
if (count > 0)
{
result = true;
}
}
return result;
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void avUserName_ServerValidate(object source, ServerValidateEventArgs args)
{
if (UserNameExists(args.Value))
{
args.IsValid = false;
}
else
{
args.IsValid = true;
}
}
/// <summary>
/// 插入数据到数据库中
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnSubmit_Click(object sender, EventArgs e)
{
string conString = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
string insertString = "insert into User_Info(UserName,UserPwd) values(@UserName,@UserPwd)";
SqlConnection conn = new SqlConnection(conString);
SqlCommand cmd = new SqlCommand(insertString,conn);
cmd.Parameters.AddWithValue("@UserName",txtUserName.Text);
cmd.Parameters.AddWithValue("@UserPwd", txtUserPwd.Text);
using (conn)
{
conn.Open();
cmd.ExecuteNonQuery();
}
txtUserName.Text = string.Empty;
txtUserPwd.Text = string.Empty;
}
}
这个页面演示了如何使用AjaxValidator控件。页面处理AjaxValidator控件的ServerValidate事件以后将一个自定义验证方法关联到控件上。
页面输入用户名和密码以后,提交表单这些字段的值就会插入到数据库User_Info中。
在后台代码,验证方法检查用户名在数据库中是否已经存在,如果输入的用户名已经存在,就会显示一个验证错误。提交表单返回到服务端之前,这个信息就会显示在浏览器中。
AjaxValidator可以关联任何服务器端验证方法。
数据库建表语句
Code
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[User_Info](
[id] [int] IDENTITY(1,1) NOT NULL,
[UserName] [varchar](50) NOT NULL,
[UserPwd] [varchar](50) NOT NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
效果截图: