js调用webService

 参考:JavaScript SOAP Client - CodeProject

soapclient.js 支持返回DataSet,DataTable(必须有显示名称)

/*****************************************************************************\

 Javascript "SOAP Client" library
 
 @version: 2.4 - 2007.12.21
 @author: Matteo Casati - http://www.guru4.net/
 
\*****************************************************************************/

class SOAPClientParameters {
	#pp = new Array();
	constructor() {
	}
	add(name, value) {
		this.#pp[name] = value;
		return this;
	}
	all() {
		return this.#pp;
	}
	toXml() {
		var xml = "";
		for (var p in this.#pp) {
			switch (typeof (this.#pp[p])) {
				case "string":
				case "number":
				case "boolean":
				case "object":
					xml += "<" + p + ">" + SOAPClientParameters.#serialize(this.#pp[p]) + "</" + p + ">";
					break;
				default:
					break;
			}
		}
		return xml;
	}
	static #serialize(o) {
		var s = "";
        if(o === null || o === undefined) return s;
		switch (typeof (o)) {
			case "string":
				s += o.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); break;
			case "number":
			case "boolean":
				s += o.toString(); break;
			case "object":
				// Date
				if (o.constructor.toString().indexOf("function Date()") > -1) {

					var year = o.getFullYear().toString();
					var month = (o.getMonth() + 1).toString(); month = (month.length == 1) ? "0" + month : month;
					var date = o.getDate().toString(); date = (date.length == 1) ? "0" + date : date;
					var hours = o.getHours().toString(); hours = (hours.length == 1) ? "0" + hours : hours;
					var minutes = o.getMinutes().toString(); minutes = (minutes.length == 1) ? "0" + minutes : minutes;
					var seconds = o.getSeconds().toString(); seconds = (seconds.length == 1) ? "0" + seconds : seconds;
					var milliseconds = o.getMilliseconds().toString();
					var tzminutes = Math.abs(o.getTimezoneOffset());
					var tzhours = 0;
					while (tzminutes >= 60) {
						tzhours++;
						tzminutes -= 60;
					}
					tzminutes = (tzminutes.toString().length == 1) ? "0" + tzminutes.toString() : tzminutes.toString();
					tzhours = (tzhours.toString().length == 1) ? "0" + tzhours.toString() : tzhours.toString();
					var timezone = ((o.getTimezoneOffset() < 0) ? "+" : "-") + tzhours + ":" + tzminutes;
					s += year + "-" + month + "-" + date + "T" + hours + ":" + minutes + ":" + seconds + "." + milliseconds + timezone;
				}
				// Array
				else if (o.constructor.toString().indexOf("function Array()") > -1) {
					for (var p in o) {
						if (!isNaN(p))   // linear array
						{
							(/function\s+(\w*)\s*\(/ig).exec(o[p].constructor.toString());
							var type = RegExp.$1;
							switch (type) {
								case "":
									type = typeof (o[p]);
								case "String":
									type = "string"; break;
								case "Number":
									type = "int"; break;
								case "Boolean":
									type = "bool"; break;
								case "Date":
									type = "DateTime"; break;
							}
							s += "<" + type + ">" + SOAPClientParameters.#serialize(o[p]) + "</" + type + ">"
						}
						else    // associative array
							s += "<" + p + ">" + SOAPClientParameters.#serialize(o[p]) + "</" + p + ">"
					}
				}
				// Object or custom function
				else
					for (var p in o)
						s += "<" + p + ">" + SOAPClientParameters.#serialize(o[p]) + "</" + p + ">";
				break;
			default:
				break; // throw new Error(500, "SOAPClientParameters: type '" + typeof(o) + "' is not supported");
		}
		return s;
	}
}

class SOAPClient {
	static #cache = new Array();
	constructor(url, userName, password) {
		this.url = url;
		this.userName = userName;
		this.password = password;
		this.#getWsdl();
	}
	#getWsdl() {
		if (!this.url) return;
		var wsdl = SOAPClient.#cache[this.url];
		if (wsdl + "" != "" && wsdl + "" != "undefined") {
			return;
        }
		var xmlHttp = SOAPClient.#getXmlHttp();
		xmlHttp.open("GET", this.url + "?wsdl", true);
		xmlHttp.onreadystatechange = () => {
			if (xmlHttp.readyState == 4) {
				SOAPClient.#cache[this.url] = xmlHttp.responseXML;
            }
		}
		xmlHttp.send(null);
    }
	#loadWsdl(method, parameters, async, callback) {
		// load from cache?
		var wsdl = SOAPClient.#cache[this.url];
		if (wsdl + "" != "" && wsdl + "" != "undefined")
			return this.#sendSoapRequest(method, parameters, async, callback, wsdl);
		// get wsdl
		var xmlHttp = SOAPClient.#getXmlHttp();
		xmlHttp.open("GET", this.url + "?wsdl", async);
		if (async) {
			xmlHttp.onreadystatechange = () => {
				if (xmlHttp.readyState == 4)
					this.#onLoadWsdl(method, parameters, async, callback, xmlHttp);
			}
		}
		xmlHttp.send(null);
		if (!async)
			return this.#onLoadWsdl(method, parameters, async, callback, xmlHttp);
	}
	#onLoadWsdl(method, parameters, async, callback, req) {
		var wsdl = req.responseXML;
		SOAPClient.#cache[this.url] = wsdl;	// save a copy in cache
		return this.#sendSoapRequest(method, parameters, async, callback, wsdl);
	}
	#sendSoapRequest(method, parameters, async, callback, wsdl) {
		// get namespace
		var ns = (wsdl.documentElement.attributes["targetNamespace"] + "" == "undefined") ? wsdl.documentElement.attributes.getNamedItem("targetNamespace").nodeValue : wsdl.documentElement.attributes["targetNamespace"].value;
		// build SOAP request
		var sr =
			"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
			"<soap:Envelope " +
			"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
			"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
			"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
			"<soap:Body>" +
			"<" + method + " xmlns=\"" + ns + "\">" +
			parameters.toXml() +
			"</" + method + "></soap:Body></soap:Envelope>";
		// send request
		var xmlHttp = SOAPClient.#getXmlHttp();
		if (this.userName && this.password) {
			xmlHttp.open("POST", this.url, async, this.userName, this.password);
			// Some WS implementations (i.e. BEA WebLogic Server 10.0 JAX-WS) don't support Challenge/Response HTTP BASIC, so we send authorization headers in the first request
			xmlHttp.setRequestHeader("Authorization", "Basic " + SOAPClient.#toBase64(this.userName + ":" + this.password));
		}
		else
			xmlHttp.open("POST", this.url, async);
		var soapaction = ((ns.lastIndexOf("/") != ns.length - 1) ? ns + "/" : ns) + method;
		xmlHttp.setRequestHeader("SOAPAction", soapaction);
		xmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
		if (async) {
			xmlHttp.onreadystatechange = () => {
				if (xmlHttp.readyState == 4)
					this.#onSendSoapRequest(method, async, callback, wsdl, xmlHttp);
			}
		}
		xmlHttp.send(sr);
		if (!async)
			return this.#onSendSoapRequest(method, async, callback, wsdl, xmlHttp);
	}
	#onSendSoapRequest(method, async, callback, wsdl, req) {
		var o = null;
		var nd = SOAPClient.#getElementsByTagName(req.responseXML, method + "Response");
		if (nd.length == 0)
			nd = SOAPClient.#getElementsByTagName(req.responseXML, "return");	// PHP web Service?
		if (nd.length == 0) {
			if (req.responseXML.getElementsByTagName("faultcode").length > 0) {
				if (async || callback)
					o = new Error(500, req.responseXML.getElementsByTagName("faultstring")[0].childNodes[0].nodeValue);
				else
					throw new Error(500, req.responseXML.getElementsByTagName("faultstring")[0].childNodes[0].nodeValue);
			}
		}
		else
			o = SOAPClient.#soapresult2object(nd[0], wsdl);
		if (callback)
			callback(o, req.responseXML);
		if (!async)
			return o;
	}
	static #soapresult2object(node, wsdl) {
		var wsdlTypes = SOAPClient.#getTypesFromWsdl(wsdl);
		return SOAPClient.#node2object(node, wsdlTypes);
	}
	static #node2object(node, wsdlTypes,varTypes) {
		// null node
		if (node == null)
			return null;
		// text node
		if (node.nodeType == 3 || node.nodeType == 4)
			return SOAPClient.#extractValue(node, wsdlTypes, varTypes);
		// leaf node
		if (node.childNodes.length == 1 && (node.childNodes[0].nodeType == 3 || node.childNodes[0].nodeType == 4))
			return SOAPClient.#node2object(node.childNodes[0], wsdlTypes, varTypes);
		var isarray = SOAPClient.#getTypeFromWsdl(node.nodeName, wsdlTypes, varTypes).toLowerCase().indexOf("arrayof") != -1;
		// object node
		if (!isarray) {
			var obj = null,n ="childNodes";
			if (node.hasChildNodes()) {
				if (node[n].length == 2
					&& node[n][1].tagName == "diffgr:diffgram") {
					//xs:schema,xs:element,xs:complexType,xs:choice
					return SOAPClient.#resolveDataSet(node[n][0][n][0][n][0][n][0], node[n][1][n][0], wsdlTypes);
				}

				obj = new Object();
				for (var i = 0; i < node[n].length; i++) {
					var p = SOAPClient.#node2object(node[n][i], wsdlTypes,varTypes);
					obj[node[n][i].nodeName] = p;
				}
			}
			return obj;
		}
		// list node
		else {
			// create node ref
			var l = new Array();
			for (var i = 0; i < node.childNodes.length; i++)
				l[i] = SOAPClient.#node2object(node.childNodes[i], wsdlTypes, varTypes);
			return l;
		}
		return null;
	}
	static #resolveDataSet(schema,node, wsdlTypes) {
		var obj = new Object(), schemaTypes = new Object();
		for (var i = 0, j = schema.childNodes.length; i < j; i++) {
			var key = schema.childNodes[i].getAttribute("name");
			obj[key] = [];
			schemaTypes[key] = SOAPClient.#getTypesFromWsdl(schema.childNodes[i], "xs");
		}
		for (var i = 0, j = node.childNodes.length; i < j; i++) {
			var n = node.childNodes[i], key = n.tagName;
			obj[key].push(SOAPClient.#node2object(n, wsdlTypes, schemaTypes[key]));
		}
		return obj;
    }
	static #extractValue(node, wsdlTypes,varTypes) {
		var value = node.nodeValue;
		switch (SOAPClient.#getTypeFromWsdl(node.parentNode.nodeName, wsdlTypes, varTypes).toLowerCase()) {
			default:
			case "s:string":
			case "xs:string":
			case "s:long":
			case "xs:long":
			case "s:double":
			case "xs:double":
				return (value != null) ? value + "" : "";
			case "s:boolean":
			case "xs:boolean":
				return value + "" == "true" || value + "" == "True";
			case "s:int":
			case "xs:int":
				return (value != null) ? parseInt(value + "", 10) : 0;
			case "s:datetime":
			case "xs:datetime":
				if (value == null)
					return null;
				else {
					value = value + "";
					value = value.substring(0, (value.lastIndexOf(".") == -1 ? value.length : value.lastIndexOf(".")));
					value = value.replace(/T/gi, " ");
					value = value.replace(/-/gi, "/");
					var d = new Date();
					d.setTime(Date.parse(value));
					return d;
				}
		}
	}
	static #getTypesFromWsdl = function (wsdl, prefix) {
		var wsdlTypes = new Array();
		prefix = prefix || "s";
		// IE
		var ell = wsdl.getElementsByTagName(prefix + ":element");
		var useNamedItem = true;
		// MOZ
		if (ell.length == 0) {
			ell = wsdl.getElementsByTagName("element");
			useNamedItem = false;
		}
		for (var i = 0; i < ell.length; i++) {
			if (useNamedItem) {
				if (ell[i].attributes.getNamedItem("name") != null && ell[i].attributes.getNamedItem("type") != null)
					wsdlTypes[ell[i].attributes.getNamedItem("name").nodeValue] = ell[i].attributes.getNamedItem("type").nodeValue;
			}
			else {
				if (ell[i].attributes["name"] != null && ell[i].attributes["type"] != null)
					wsdlTypes[ell[i].attributes["name"].value] = ell[i].attributes["type"].value;
			}
		}
		return wsdlTypes;
	}
	static #getTypeFromWsdl = function (elementname, wsdlTypes, varTypes) {
		var type = varTypes && varTypes[elementname];
		if (!type) {
			type = wsdlTypes[elementname] + "";
        }
		return type == "undefined" ? "" : type;
	}
	// private: utils
	static #getElementsByTagName = function (document, tagName) {
		try {
			// trying to get node omitting any namespaces (latest versions of MSXML.XMLDocument)
			return document.selectNodes(".//*[local-name()=\"" + tagName + "\"]");
		}
		catch (ex) { }
		// old XML parser support
		return document.getElementsByTagName(tagName);
	}
	// private: xmlhttp factory
	static #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;
			}
			if (window.ActiveXObject)
				return new ActiveXObject(SOAPClient.#getXmlHttpProgID());
		}
		catch (ex) { }
		throw new Error("Your browser does not support XmlHttp objects");
	}
	static #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");
	}

	static #toBase64 = function (input) {
		var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;
		do {
			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);

			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;

			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}

			output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
				keyStr.charAt(enc3) + keyStr.charAt(enc4);
		} while (i < input.length);

		return output;
	}
	invoke(method, parameters, async, callback) {

		if (!parameters) {
			parameters = new SOAPClientParameters();
		}

		if (async)
			this.#loadWsdl(method, parameters, async, callback);
		else
			return this.#loadWsdl(method, parameters, async, callback);
	}
}

webservice.asmx

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace WebApp
{
    /// <summary>
    /// WebService 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 
    // [System.Web.Script.Services.ScriptService]
    public class WebService : System.Web.Services.WebService
    {

        [WebMethod(Description = "HelloWorld")]
        public string HelloWorld(string id, string name, out string msg, out DataSet ds)
        {
            msg = "HelloWorld";
            ds = new DataSet("data");
            DataTable table = new DataTable();
            table.Columns.Add("total", typeof(int));
            table.Rows.Add(92);
            ds.Tables.Add(table);
            table = new DataTable();
            table.Columns.Add("name");
            table.Columns.Add("type");
            table.Columns.Add("code");
            table.Columns.Add("value",typeof(int));
            table.Rows.Add("苹果", "水果", "apple", 11);
            table.Rows.Add("香梨", "水果", "pear", 9);
            ds.Tables.Add(table);
            return "success";
        }

        [WebMethod(Description = "RetDataSet")]
        public DataSet RetDataSet()
        {
            DataSet ds = new DataSet("data");
            DataTable table = new DataTable();
            table.Columns.Add("total", typeof(int));
            table.Rows.Add(80);
            ds.Tables.Add(table);
            return ds;
        }

        [WebMethod(Description = "RetDataTable")]
        public DataTable RetDataTable()
        {
            DataTable table = new DataTable("table");
            table.Columns.Add("name");
            table.Columns.Add("type");
            table.Columns.Add("code");
            table.Columns.Add("value", typeof(int));
            table.Rows.Add("苹果", "水果", "apple", 11);
            table.Rows.Add("香梨", "水果", "pear", 9);
            return table;
        }

        [WebMethod(Description = "GetList")]
        public string GetList(int pageNo,int pageSize, out string msg, out List<Fruit> list)
        {
            msg = "测试接口";
            list = new List<Fruit>()
            {
                new Fruit{ id="1",name="苹果",code="apple",num=10},
                new Fruit{ id="2",name="香梨",code="pear",num=3}
            };

            return "ok";
        }
    }

    public class Fruit
    {
        public string id { get; set; }
        public string name { get; set; }
        public string code { get; set; }
        public int num { get; set; }
    }
}

test.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>测试页面</title>
    <script src="soapclient.js"></script>
</head>
<body>
    <button onclick="test()">测试</button>
    <script>
        var url = "WebService.asmx";
        var p = new SOAPClientParameters();
        p.add("id", "20210610");
        p.add("name", "测试");
        let client = new SOAPClient(url);

        function helloWorldCallback(r) {
            console.log(r);
        }

        function test() {
            //client.invoke("HelloWorld", p, true, helloWorldCallback);
            //client.invoke("RetDataSet", null, true, helloWorldCallback);
            client.invoke("RetDataTable", null, true, helloWorldCallback);
            client.invoke("GetList", null, true, helloWorldCallback);
            
        }
    </script>
</body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

闪耀星星

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

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

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

打赏作者

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

抵扣说明:

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

余额充值