65.9K
CodeProject 正在变化。 阅读更多。
Home

如何使用 JS 通过 POST 同时调用 SOAP 和 JSON Web 服务

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.29/5 (6投票s)

2009年4月8日

CPOL

2分钟阅读

viewsIcon

73922

downloadIcon

324

WebService 同时支持 SOAP 和 JSON

引言

这里提供一个完整的示例,展示如何使用 JS 通过 Post 方法调用 WebService,同时支持 SOAP 和 JSON。

背景

现在几乎每个人都在谈论 Ajax 和 WebService。我也尝试了,并编写了一个 JS 来完成这项工作!阅读我的文章后,你会发现事情其实很简单!

我的示例有一些不同之处。它确实可以在 Internet Explorer 6、Internet Explorer 7、Opera 和 Netscape 中正常工作。你会发现,在 Firefox3 中,它不支持同步函数来调用 WebService。我还发现我们无法在 Internet Explorer 6 中创建超过一个 xmlhttprequest 对象。我已经修复了这个问题。它运行良好,但不支持 Internet Explorer 5,因为它不支持 push() 函数。我还没有尝试在 Internet Explorer 5 中测试它。

你可能需要知道,xmlhttprequest 不支持跨域 WebService。

Using the Code

这里是 kuuy.SoapRequest.js 文件

   (function() {
    //If you read the oriented Ajax JS, it's used to register a namespace
    var Namespace = {
        Register: function(_Name) {
            var o = window;
            var x = false;
            for (var a = _Name.split("."); a.length > 0; ) {
                //remove the top element
                var s = a.shift();
                if (a.length == 0) { if (o[s]) { x = true; } }
                if (!o[s]) { o[s] = {}; }
                o = o[s];
            }
            if (x) { return 1; }
        }
    }
    Namespace.Register("kuuy");
    var xmlPId = null;
    //XMLparser,we call it ajax activeobject
    var xmlHttp = (function() {
        if (window.XMLHttpRequest) {
            return new XMLHttpRequest();
        }
        else {
            if (xmlPId) {
                return new ActiveXObject(xmlPId);
            }
            else {
                var parserIds = ["Msxml2.XMLHTTP.6.0", 
		"MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
                for (var pid in parserIds) {
                    try {
                        xmlPId = pid;
                        return new ActiveXObject(parserIds[pid]);
                    } catch (e) { }
                }
                throw new Error("don't support the xmlrequest object~!");
            }
        }
    })();
    //Parameter
    kuuy.Parameter = function() {
        return {
            Name: null,
            Value: null,
            Init: function() {
                if (arguments[0].length == 2) 
		{ this.Name = arguments[0][0]; this.Value = arguments[0][1]; }
                return this;
            }
}.Init(arguments);
        }
        //SOAPRequest,We Instanced it,and then call the method Open
        kuuy.SOAPRequest = function() {
            return {
                URL: null, //url
                Method: null, //the method we calling
                Params: null, //parameters
                Callback: null, //callback a function
                WSDLS: null, //webservice descriptions
                Init: function() {
                    switch (arguments[0].length) {
                        case 2:
                            this.URL = arguments[0][0];
                            this.Callback = arguments[0][1];
                            break;
                        case 3:
                            this.URL = arguments[0][0];
                            this.Method = arguments[0][1];
                            this.Callback = arguments[0][2];
                            this.WSDLS = new Array();
                            break;
                    }
                    this.Params = new Array();
                    return this;
                },
                AddParam: function()//add a parameter
                {
                    switch (arguments.length) {
                        case 1: this.Params.push(arguments[0]); break;
                        case 2: this.Params.push
			(new kuuy.Parameter(arguments[0], arguments[1])); break;
                    }
                },
              //Open the request
                Open: function() {
                    var obj = this;
                    if (this.WSDLS) {
                        var wsdl = this.WSDLS[this.URL];
                        if (!wsdl) {
                            xmlHttp.open
				("GET", this.URL + "?wsdl", true); //async request
                            xmlHttp.onreadystatechange = function() {
                                if (xmlHttp.readyState == 4) {
                                    if (xmlHttp.status == 200 || xmlHttp.status == 0) {
                                       //the soap request
                (function() { obj.Post.call(obj, xmlHttp.responseXML); })();
                                    }
                                }
                            };
                            xmlHttp.send(null);
                        }
                        else
                            (function() { obj.Post.call(this); })();
                    }
                    else {
                        var data = "";
                        for (var par in this.Params) {
                            data += this.Params[par].Name + 
					"=" + this.Params[par].Value;
                        }
                        xmlHttp.open("POST", this.URL, true); //asnyc request
                        xmlHttp.setRequestHeader("Content-type", 
				"application/x-www-form-urlencoded");
                        xmlHttp.setRequestHeader("Content-Length", data.length);
                        xmlHttp.onreadystatechange = function() {
                            if (xmlHttp.readyState == 4) {
                                if (xmlHttp.status == 200 || xmlHttp.status == 0) {
                                    obj.Callback(xmlHttp.responseText);
                                }
                            }
                        }
                        xmlHttp.send(data);
                    }
                },
                Post: function() {
                    if (!this.WSDLS[this.URL])
                        this.WSDLS[this.URL] = arguments[0];
                    var wsdl = this.WSDLS[this.URL];
                    var ns = (wsdl.documentElement.attributes["targetNamespace"] + 
				"" == "undefined") ? 
                    wsdl.documentElement.attributes.getNamedItem
				("targetNamespace").nodeValue : 
			wsdl.documentElement.attributes["targetNamespace"].value;
                    //method we calling
                    var soapaction = ((ns.lastIndexOf("/") 
			!= ns.length - 1) ? ns + "/" : ns) + this.Method;
                    var parsXml = "";
                    for (var par in this.Params) {
                        parsXml += "<" + this.Params[par].Name + ">" + 
			this.Params[par].Value + "</" + 
					this.Params[par].Name + ">"; ;
                    }
                    var data = "<?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>" +
                        "<" + this.Method + " xmlns=\"" + ns + "\">" +
                        parsXml +
                        "</" + this.Method + "></soap:Body></soap:Envelope>";
                    xmlHttp.open("POST", this.URL, true); //asyc request
                    xmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
                    xmlHttp.setRequestHeader("SOAPAction", soapaction);
                    xmlHttp.setRequestHeader("Content-Length", data.length);
                    var obj = this;
                    xmlHttp.onreadystatechange = function() {
                        if (xmlHttp.readyState == 4) {
                            if (xmlHttp.status == 200 || xmlHttp.status == 0) {
                                obj.Callback(xmlHttp.responseText);
                            }
                        }
                    }
                    xmlHttp.send(data);
                }
}.Init(arguments);
            }
        })();

然后我们需要一个在 .NET 3.5 中名为 EnhancedWebService 的类。DataContractJsonSerializer 使得使用 JSON 更加容易。我们还需要一个名为 JSONHelper 的类,用于序列化和反序列化 JSON 对象。

这里是 JSONHelper.cs 类的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Json;
using System.IO;
namespace kuuy.Components
{
    public class JSONHelper
    {
        //Serialize
        public static string Serialize<T>(T obj)
        {
            string reVal = string.Empty;
            using (MemoryStream m = new MemoryStream())
            {
                DataContractJsonSerializer serializer = 
			new DataContractJsonSerializer(obj.GetType());
                serializer.WriteObject(m, obj);
                reVal = Encoding.UTF8.GetString(m.ToArray());
                m.Flush();
            }
            return reVal;
        }
        //Deserialize
        public static T Deserialize<T>(string json)
        {
            return Deserialize<T>(json, Activator.CreateInstance<T>().GetType());
        }
        //Deserialize(Dynamic Type)
        public static T Deserialize<T>(string json, Type type)
        {
            T obj = Activator.CreateInstance<T>();//Instance
            using (MemoryStream m = new MemoryStream(Encoding.UTF8.GetBytes(json)))
            {
                DataContractJsonSerializer serializer = 
			new DataContractJsonSerializer(type);
                obj = (T)serializer.ReadObject(m);
                m.Flush();
            }
            return obj;
        }
    }
}

别忘了添加 System.ServiceModel.Web 的引用。

这里是 EnhancedWebService.cs 的代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;
using System.IO;
using System.Web;
namespace kuuy.Components.Services
{
    //WebService Extension
    public class EnhancedWebService : System.Web.Services.WebService
    {
        public EnhancedWebService()
            : base()	//Base Construct
        {
            string ServiceMethodName = GetMethodName();
            bool IsJSON = Context.Request.QueryString["out"] == "json";
            if (IsJSON) InterceptJSONMethodRequest(ServiceMethodName);
        }
        private string GetMethodName()//Get the method we are calling
        {
            return Context.Request.Url.Segments
		[Context.Request.Url.Segments.Length - 1];//URL Segment('\')
        } 
        private void InterceptJSONMethodRequest(string ServiceMethodName)
        {
            JSONMethodAttribute JMA = GetMethodJSONMethodAttribute
			(ServiceMethodName);//Description Class
            if (JMA == null)
            {
                Context.Response.Write("throw new Exception('The Web Service method " +
                                       ServiceMethodName + " is not available " +
                                       "as a JSON function. For more " +
                                       "information contact " +
                                       "the Web Service Administrators.');");
            }
            else
            {
                //ToDo: deserialize parameters, call target method, 
                //      deserialize and write return value
                Type Service = this.GetType();
                MethodInfo JSONMethod = 
		Service.GetMethod(ServiceMethodName);//Get Parameters
                if (JSONMethod == null) return;
                //Parameters
                ParameterInfo[] JSONMethodParameters = JSONMethod.GetParameters();
                object[] CallParameters = new object[JSONMethodParameters.Length];
              
                for (int i = 0; i < JSONMethodParameters.Length; i++)
                {
                    //Parameter
                    ParameterInfo TargetParameter = JSONMethodParameters[i];
                    string RawParameter = HttpUtility.UrlDecode
			(Context.Request.Form[TargetParameter.Name]);//Get Value
                    if (RawParameter == null || RawParameter == "")
                        throw new Exception("Missing parameter " + 
				TargetParameter.Name + ".");
                    CallParameters[i] = JSONHelper.Deserialize<object>
				(RawParameter, TargetParameter.ParameterType);
                }
                object JSONMethodReturnValue = JSONMethod.Invoke(this, CallParameters);
                string SerializedReturnValue = 
			JSONHelper.Serialize<object>
			(JSONMethodReturnValue);//Return JSON Object
                Context.Response.Write(SerializedReturnValue);
            }
            Context.Response.Flush();
            Context.Response.End();
        }
        private JSONMethodAttribute GetMethodJSONMethodAttribute
			(string WebServiceMethodName)
        {
            MethodInfo ActiveMethod = this.GetType().GetMethod(WebServiceMethodName);
            JSONMethodAttribute JMA = null;
            if (ActiveMethod != null)
            {
                object[] Attributes = ActiveMethod.GetCustomAttributes(true);
                foreach (object Attribute in Attributes)
                {
                    if (Attribute.GetType() == typeof(JSONMethodAttribute))
                    {
                        JMA = (JSONMethodAttribute)Attribute;
                    }
                }
            }
            return JMA;
        }
    }
    //WebService Description
    public class JSONMethodAttribute : System.Attribute
    {
        public JSONMethodAttribute()
        {
        }
    }
}

现在所有代码都已显示在上方。我们需要让它工作起来。这是我的示例

<!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>
    <title></title>
    <script src="js/kuuy.SOAPRequest.js" type="text/javascript"></script>
    <script type="text/javascript">
        var pattern = /webservice\.htm/gi;
        var callback = function(o) {
            alert(o);
        }
        function JSONRequest() {
            var url = document.location.href.replace
		(pattern, "WebService1.asmx/JSONService?out=json");
            var request = new kuuy.SOAPRequest(url, callback);
            request.AddParam("input", "88.88.88.88");
            request.Open(); 	//Send SOAP Request
        }
        function SOAPRequest() {
            var url = document.location.href.replace(pattern, "WebService1.asmx");
            var method = "JSONService";
            var request = new kuuy.SOAPRequest(url, method, callback);
            request.AddParam("input", "88.88.88.88");
            request.Open(); 	//Send SOAP Request
        }
    </script>
</head>
<body>
    <input type="button" onclick="JSONRequest()" value="JOSN"/>
    <input type="button" onclick="SOAPRequest()" value="SOAP"/>
</body>
</html>

你可以下载我的完整示例。它非常简单有效。祝你好运!

虽然我没有工作,也没有人会雇佣我,但我从未停止学习。我希望这能帮助你!感谢阅读!

如果你有任何问题,可以发送邮件至 kuuy@hotmail.com

历史

  • 2009-04-07 初始发布
© . All rights reserved.