有些事情做起来很别扭,但不是不能做!
在最常见的验证用户名是否存在的功能中,我以前常用xmlhttp请求一个页面来验证,这种方式简单,如下面代码所示:
前台JS代码


function xmlhttp(){
var obj;
this.requestBuf = null;
this.charset = 'utf-8';
this.sendData = '';
this.regAxObject = function(){
if(obj) return true;
if (window.ActiveXObject){
try{
obj = new ActiveXObject('MSXML2.XMLHTTP');
} catch(e){
try{
obj = new ActiveXObject('Microsoft.XMLHTTP');
} catch(e){
return false;
}
}
} else if(window.XMLHttpRequest){
try{
obj = new XMLHttpRequest();
} catch(e){
return false;
}
} else{
return false;
}
return true;
}
this.request = function(){
if(!this.regAxObject()){
return false;
}
if(arguments[0]) this.url = arguments[0];
if(arguments[1] || arguments[1] == '') this.sendData = arguments[1];
if(this.sendData != ''){
obj.open('post',this.url,false);
obj.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
obj.setRequestHeader('Content-Length',this.sendData.length);
obj.send(this.sendData);
} else {
obj.open('get',this.url,false);
obj.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
obj.setRequestHeader('Content-Type', 'text/html;charset=' + this.charset);
obj.send(null);
}
if(obj.readyState == 4){
if(obj.status == 404){
return false;
}
if(obj.status == 200){
this.requestBuf = obj.responseText;
return obj.responseText;
}
}
}
}
function checkIsValid(sender, args){
args.IsValid = ('true' == new xmlhttp().request("/userIsValid.aspx","logname=" + args.Value))
}
后台页面代码:


<%@ WebHandler Language="C#" Class="checkIsValid" %>
using System;
using System.Web;
public class checkIsValid : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
string logName = context.Request["logname"];
string ret = "false";
if (logName.StartsWith("abc"))
{
ret = "true";
}
context.Response.Write(ret);
}
public bool IsReusable {
get {
return false;
}
}
}
这种方式,只需在后台写一个HttpHandler,处理一下这个请求,返回true|false就行,当然要做一下安全检查,如这个IP今天提交的频率。我个人感觉这个方法简单有效!
但今天的话题是,如果非要用CustomValidator+WebService+asp.net ajax进行验证呢?最烦较真说不能。写了一个很别扭的实现示例如下:
// use by FF to findout event object
function searchEvent()
{
func = searchEvent.caller;
while(func != null)
{
var arg0 = func.arguments[0];
if( arg0 )
{
if( arg0.constructor == Event) // Got it
return arg0;
}
func = func.caller;
}
return null;
}
//自定义验证函数,这个函数将被执行两次 coder:evlon#126.com
function checkIsValid(sender, args){
if(!sender.valid_result){
sender.valid_result = {validing :false,result: null};
}
if(!sender.valid_result.validing) {
//第一次,要调用WEB服务去检查
var e = window.event || searchEvent(); //得到事件
var targetedControl; //通过下面的步骤,去找到事件源
if ((typeof(e.srcElement) != "undefined") && (e.srcElement != null)) {
targetedControl = e.srcElement;
}
else {
targetedControl = e.target;
}
//给事件源加上一点自定义的信息
sender.valid_result.validing = true;
//调用WEB服务,并生成要传递的上下文
User.CheckIsValid(args.Value,checkIsValidResult,null,{sender:sender,args:args,targetedControl:targetedControl});
}
else {
//第二次执行了,直接从sender中取出结果,返回
args.IsValid = sender.valid_result.result;
sender.valid_result.validing = false;
}
}
function checkIsValidResult(result, context) {
//把WEB服务的返回结果,保存在事件源中
context.sender.valid_result.result = result;
//再次引发onchange,从而验证
if(context.targetedControl.fireEvent)
{
context.targetedControl.fireEvent('onchange');
}
else
{
var e = document.createEvent('MouseEvents');
e.initEvent("change", true, true);
context.targetedControl.dispatchEvent(e);
}
}
function searchEvent()
{
func = searchEvent.caller;
while(func != null)
{
var arg0 = func.arguments[0];
if( arg0 )
{
if( arg0.constructor == Event) // Got it
return arg0;
}
func = func.caller;
}
return null;
}
//自定义验证函数,这个函数将被执行两次 coder:evlon#126.com
function checkIsValid(sender, args){
if(!sender.valid_result){
sender.valid_result = {validing :false,result: null};
}
if(!sender.valid_result.validing) {
//第一次,要调用WEB服务去检查
var e = window.event || searchEvent(); //得到事件
var targetedControl; //通过下面的步骤,去找到事件源
if ((typeof(e.srcElement) != "undefined") && (e.srcElement != null)) {
targetedControl = e.srcElement;
}
else {
targetedControl = e.target;
}
//给事件源加上一点自定义的信息
sender.valid_result.validing = true;
//调用WEB服务,并生成要传递的上下文
User.CheckIsValid(args.Value,checkIsValidResult,null,{sender:sender,args:args,targetedControl:targetedControl});
}
else {
//第二次执行了,直接从sender中取出结果,返回
args.IsValid = sender.valid_result.result;
sender.valid_result.validing = false;
}
}
function checkIsValidResult(result, context) {
//把WEB服务的返回结果,保存在事件源中
context.sender.valid_result.result = result;
//再次引发onchange,从而验证
if(context.targetedControl.fireEvent)
{
context.targetedControl.fireEvent('onchange');
}
else
{
var e = document.createEvent('MouseEvents');
e.initEvent("change", true, true);
context.targetedControl.dispatchEvent(e);
}
}
后台的代码很简单,只是一个WEB服务:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
/// <summary>
///User 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
//若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
[System.Web.Script.Services.ScriptService]
public class User : System.Web.Services.WebService
{
public User()
{
//如果使用设计的组件,请取消注释以下行
//InitializeComponent();
}
[WebMethod]
public bool CheckIsValid(string logName)
{
return logName.StartsWith("abc");
}
}
现在好了,简单的一行代码,现在变成了N行,确实是一个别扭的实现吧?
不过,这里确实有几个知识点:
1. 在FF中查找事件
2. FF中的FireEvent
请博友们指正。