一个调用ATL Server WebServices 的AJAX客户端

请将下面的代码完整复制到soapclient.js中

/*****************************************************************************
 AJAX
 Javascript "SOAP Client" library
 Thank to Mr.Matteo Casati, Ihar Voitka - http://www.guru4.net/
 Author: ZhangLiang, E-Mail:cheungmine@gmail.com
 Date: 2006-8-31
****************************************************************************
*/

function  _debug(rownum, msg)  {    alert(rownum+":"+msg);  }

var  SOAP_SUCCESS  =   0 ;
var  SOAP_FAULT  =   1 ;

var  _sr_env_hdr_  =    " <soap:Envelope  "   +
     
" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"  "   +  
     
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  "   +  
     
" xmlns:xsd="http://www.w3.org/2001/XMLSchema"  "   +  
     
" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> " ;
               
var  _sr_body_hdr_  =   " <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> " ;

var  _soap_header_m_token_  =   "" ;         //  global varible, soap_header: m_token

function  SOAPParams(callid, url, method, async, callback, username, password)
{
    
this.callid = callid;
    
this.url =     url;    // "http://localhost/MtkWebgisServer/MtkWebgis.dll?Handler=GenMtkWebgisWSDL";
    this.svc = null;    //"http://cl2/MtkWebgisServer/MtkWebgis.dll?Handler=Default";    // 未完
    this.method = method;
        
    
if (async+"" == "undefined")
        
this.async = true;                    // default value
    else
        
this.async = async;
        
    
if (this.async){
        
if (callback+"" == "undefined")
            
this.callback = soap_callback;
        
else
            
this.callback = callback;
    }

        
    
this.username = null;
    
if (username+"" != "")
        
this.username = username;
        
    
this.password = null;
    
if (password+"" != "")
        
this.password = password;
        
    
this.wsdl = null;
    
this.result = SOAP_FAULT;
    
this.xmlhttp = null;            // xmlhttp object returned
    
    
this._pl = new Array();            // input parameters list
        
    
this.add = function(name, value){
        
this._pl[name] = value;
        
return this;
    }

    
    
this.toXml = function(){
        
var xml = "";
        
for(var p in this._pl){
            
var t = typeof(this._pl[p]);
            
if (t == "object" || t == "function")
                xml 
+= "<" + p + ">" + this._pl[p].toXml() + "</" + p + ">";
            
else
                xml 
+= "<" + p + ">" + this._pl[p].toString().replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"+ "</" + p + ">";
        }

        
return xml;    
    }

    
    
this.setToken = function(){
        
if (this.method=="login"){
            _soap_header_m_token_ 
= this.getval("snp:m_token");
        }

    }

    
    
this.getToken = function(){
        
return _soap_header_m_token_;
    }

    
    
this.getval = function(name){
        
var ret = SOAPClient._getElementsByTagName(this.xmlhttp.responseXML.documentElement, name).item(0);
        
return ret.text;    
    }

    
    
this.retval = function(){
        
return this.getval("return");
    }

        
    
// SOAP:Fault
    this.faultcode = function(){
        
return this.getval("faultcode");
    }

    
    
this.faultstring = function(){
        
return this.getval("faultstring");
    }

    
    
this.faultdetail = function(){
        
return this.getval("detail");
    }

}


function  SOAPClient() {}

SOAPClient.invoke 
=   function (params)
{
    params.result 
= SOAP_FAULT;
    
if(params.async)
        SOAPClient._loadWsdl(params);
    
else
        
return SOAPClient._loadWsdl(params);
}


//  private: wsdl cache
SOAPClient_cacheWsdl  =   new  Array();

//  private: invoke async
SOAPClient._loadWsdl  =   function (params)
{
    
// load from cache?
    params.wsdl = SOAPClient_cacheWsdl[params.url];
    
if(params.wsdl + "" != "" && params.wsdl + "" != "undefined"){
        params.svc 
= SOAPClient._getService(params.wsdl);    
        
return SOAPClient._sendSoapRequest(params);
    }

        
    
// get wsdl
    var _xmlhttp = SOAPClient._getXmlHttp();
    
    
if (params.username+"" != "undefined")
        _xmlhttp.open(
"GET", params.url, params.async, params.username, params.password);
    
else
        _xmlhttp.open(
"GET", params.url, params.async);
    
    
if(params.async){
        _xmlhttp.onreadystatechange 
= function(){
            
if(_xmlhttp.readyState == 4)
                SOAPClient._onLoadWsdl(params, _xmlhttp);
        }

    }

    
    _xmlhttp.send(
null);
    
if (!params.async)
        
return SOAPClient._onLoadWsdl(params, _xmlhttp);
}


SOAPClient._onLoadWsdl 
=   function (params, req)
{
    
if (req.readyState == 4 && req.status == 200){
        params.wsdl 
= req.responseXML;
        params.svc 
= SOAPClient._getService(params.wsdl); 
        SOAPClient_cacheWsdl[params.url] 
= params.wsdl;        // save a copy in cache
        return SOAPClient._sendSoapRequest(params);
    }

    
return SOAP_FAULT;
}


SOAPClient._sendSoapRequest 
=   function (params)
{
    
// get namespace, ok
    var ns = SOAPClient._getAttribValue(params.wsdl.documentElement, "targetNamespace");

    
// 构造SOAP请求, SOAP 2.0
    var sr =     _sr_env_hdr_ + "<soap:Header><snp:m_token xmlns:snp=""+ns+"">" + 
                _soap_header_m_token_ 
+ "</snp:m_token></soap:Header>" +
                _sr_body_hdr_ 
+ "<snp:" + params.method + " xmlns:snp="" + ns + "">" + 
                params.toXml() 
+ "</snp:" + params.method + "></soap:Body></soap:Envelope>";
    
    
// send request
    params.xmlhttp = SOAPClient._getXmlHttp();
    params.xmlhttp.open(
"POST", params.svc, params.async);
    params.xmlhttp.setRequestHeader(
"SOAPAction"""#"+params.method+""");    // SOAPAction: "#HelloWorld"
    params.xmlhttp.setRequestHeader("Content-Type""text/xml; charset=utf-8");
    
    
if(params.async){
        params.xmlhttp.onreadystatechange 
= function(){
            
if(params.xmlhttp.readyState == 4)
                SOAPClient._onSendSoapRequest(params);
        }

    }

    
    
try{
        params.xmlhttp.send(sr);
    }

    
catch(ex){}
        
    
if (!params.async)
        
return SOAPClient._onSendSoapRequest(params);
}


SOAPClient._onSendSoapRequest 
=   function (params)
{
    
if (params.xmlhttp.readyState == 4 && params.xmlhttp.status == 200){
        params.result 
= SOAP_SUCCESS;    // 未完...
        params.setToken();                // 设置全局变量: _soap_header_m_token_
    }

        
    
if(params.async && params.callback)
        params.callback(params.result, params);
    
    
if (!params.async)
        
return params.result;
}


//  private: utils
SOAPClient._getElementsByTagName  =   function (document, tagName, ns)
{    
    
try{    
        
// trying to get node omitting any namespaces (latest versions of MSXML.XMLDocument)
        var lst = document.selectNodes(".//*[local-name()=""+ tagName +""]");
        
if (lst.length == 0)
            
throw 0;
        
return lst;
    }

    
catch (ex){}
        
    
// old XML parser support
    if (ns+"" == "undefined")
        
return document.getElementsByTagName(tagName);
    
    
return document.getElementsByTagName(ns+":"+tagName);    
}


SOAPClient._getService 
=   function (wsdl)
{
    
var soap_address = SOAPClient._getElementsByTagName(wsdl.documentElement, "address""soap").item(0);
    
return SOAPClient._getAttribValue(soap_address, "location");
}


SOAPClient._getAttribValue 
=   function (node, name)
{
    
return (node.attributes[name]+"" == "undefined"? node.attributes.getNamedItem(name).nodeValue : node.attributes[name].value;
}


//  private: xmlhttp factory
SOAPClient._getXmlHttp  =   function () 
{
    
try{
        
if(window.XMLHttpRequest){
            
var req = new XMLHttpRequest();
            
// some versions of Moz do not support the readyState property and the onreadystate event so we patch it!
            if(req.readyState == null
            
{
                req.readyState 
= 1;
                req.addEventListener(
"load"
                                    
function() 
                                    
{
                                        req.readyState 
= 4;
                                        
if(typeof req.onreadystatechange == "function")
                                            req.onreadystatechange();
                                    }
,
                                    
false);
            }

            
return req;
        }

        
else if(window.ActiveXObject) {
            
return new ActiveXObject(SOAPClient._getXmlHttpProgID());
        }

    }

    
catch (ex) {}
    
    
throw new Error("Your browser does not support XmlHttp objects");
}


SOAPClient._getXmlHttpProgID 
=   function ()
{
    
if(SOAPClient._getXmlHttpProgID.progid)
        
return SOAPClient._getXmlHttpProgID.progid;
    
var progids = ["Msxml2.XMLHTTP.5.0""Msxml2.XMLHTTP.4.0""MSXML2.XMLHTTP.3.0""MSXML2.XMLHTTP""Microsoft.XMLHTTP"];
    
var o;
    
for(var i = 0; i < progids.length; i++)
    
{
        
try
        
{
            o 
= new ActiveXObject(progids[i]);
            
return SOAPClient._getXmlHttpProgID.progid = progids[i];
        }

        
catch (ex) {};
    }

    
throw new Error("Could not find an installed XML parser");
}

假设ATL XML WebServices实现方法如下:

[id( 1 ), helpstring( " 登入系统, 获得用户令牌和全图URL, 以后任何方法调用必须给出令牌 " )]

HRESULT login([
in ] BSTR Username, [ in ] BSTR Password);

id(
2 ), helpstring( " 刷新地图, 取地图imgURL " )]

HRESULT refresh([out] DOUBLE
*  Scale, [out, retval] BSTR  * imgURL);

客户端IE中调用如下:

< HTML >
    
< HEAD >
        
< TITLE > WebGis Demo Page  -  WebGis AJAX Client </ TITLE >
        
< script language = " javascript "  src = " ajax/soapclient.js " ></ script >
        
< script language = " javascript " >
            
//  WebService URL
             var  g_url  =   " http://cl2/mtkwebgis/MtkWebgis.dll?Handler=GenMtkWebgisWSDL " ;
                        
            
function  soap_callback(rcode, params)
            
{
                
if (rcode == SOAP_SUCCESS)
                
{
                    
switch (params.callid)
                    
{
                    
case "刷新":
                        imgMap.src 
= params.retval();                    // retval()    取得[out,retval]参数
                        alert( "当前比例:" + params.getval("Scale") );    // getval(...) 取得[out]参数
                        break;                    
                    }

                }

                
else
                
{
                    alert(params.callid
+":发生错误");                    
                }
                
            }

            
            
function  Login()
            
{
                
// 同步调用, 获得令牌 
                var soap = new SOAPParams("登录", g_url, "login"false);
                soap.add(
"Username""cheung");
                soap.add(
"Password""mine");
                
if (SOAP_SUCCESS == SOAPClient.invoke(soap))
                    refresh();
                
else
                    alert(
"登录失败");                    
            }

            
            
function  Refresh()
            
{
                
// 异步调用刷新, 默认回调函数soap_callback
                var soap = new SOAPParams("刷新", g_url, "refresh");
                SOAPClient.invoke(soap);
            }

        
</ script >
    
</ HEAD >
    
< BODY onload = " Login(); " >
        
< div id = " divMap " >< img id = " imgMap " ></ div >
    
</ BODY >
</ HTML >

使用soapclient.js需要注意,我假设XML WebServices必须存在如上面所示的login方法,用于验证用户,而且m_token必须是soap头。login原型如下:

[ soap_method ]
[ soap_header( value 
=   " m_token " , out  =   true  ) ]
HRESULT login(
/*[in]*/  BSTR Username,  /*[in]*/  BSTR Password)
{        
    CHAR szID[MAX_TOKEN_LEN 
+ 1];
    
*szID = 0;

    DWORD dwSize 
= MAX_TOKEN_LEN;
    HRESULT hr 
=  m_spSessionSvc->CreateNewSession(szID, &dwSize, &m_spSession);
    CHECK_FAILED(hr);

    szID[dwSize] 
= 0;
    m_token 
= CComBSTR(szID).Detach();
            
    
return hr;
}

这样,用户就可以通过soapclient.js在IE中直接调用ATL Server写的XML WebServices了。

(本文写于2006年9月,cheungmine,上海新区时空信息技术有限公司)

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

车斗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值