ASP.NET 客户端与 Axis Apache Web 服务之间的 SOAP 消息交换






3.86/5 (4投票s)
ASP.NET 客户端发送和接收来自 Java Axis Web 服务的复杂 SOAP 消息
引言
关于 ASP.NET 客户端与 Java 编写的 Web 服务之间发送 SOAP 消息的信息不多,即使存在,它也通常基于发送和接收原始数据信息,例如数字和小文本字符串。
但如果我们想在两个理论上应该透明地交换信息的平台之间交换复杂对象呢?事实是,客户端向 Web 服务发送 SOAP 请求消息(SOAP 提供了一种以 XML 格式表示消息的标准且简单的方法),Web 服务接收 XML 文档,验证它是否具有 SOAP 消息的特征(Envelope, Header, Body),处理消息并返回 SOAP 响应消息。
任何对象(无论多复杂)都会被序列化,然后被包含在 SOAP 消息中并发送到 Web 服务。如果客户端和 Web 服务中的 SOAP 消息结构相同,我们唯一需要担心的就是 Web 服务中存在正确的对象反序列化,以便消息能够被正确解释。
本文的目的是展示如何在 ASP.NET 客户端和 Java Axis Web 服务之间发送和接收复杂 SOAP 消息,而不是解释 SOAP 消息如何在每个平台上传输。这些信息可以在网上很容易地找到。
Using the Code
这里的示例包括从 C# 编写的客户端发送 XML 文档到 Java 编写的 Web 服务。Apache Axis 作为 SOAP 消息在 Apache Tomcat Web 服务器中的实现工具。这是要发送的 XML 文档的结构
Web 服务处理 XML 文档请求中的采购订单,并返回单位价格乘以数量减去折扣的总和。返回结构如下

Apache Axis Web 服务
首先,构建一个具有接收 XML 文档作为参数的方法的 Web 服务。在此之前,我们需要安装 Tomcat Apache 和必要的文件的支持,以便 Axis Apache 能够正常工作(例如 JAVA JRE 和 JDK)。构建一个 Axis Web 服务非常简单。我们必须按照以下步骤进行
- 首先,通过描述文件部署 Web 服务。为此,请创建以下文档并将其命名为deploy.wsdd。
<deployment xmlns="http ://xml.apache.org/axis/wsdd/" xmlns:java="http ://xml.apache.org/axis/wsdd/providers/java" xmlns:xsi="http ://www.w3.org/2000/10/XMLSchema - instance"> <service name="wsOrderSummary" provider="java:RPC"> <parameter name="className" value="wsOrderSummary"> <parameter name="allowedMethods" value="*"> <operation name="getOrderSummary"> <parameter name="XMLdoc" mode="IN"> </operation> </service> </deployment>
- 接下来,执行部署文件以更新 Axis 服务器。在 DOS 命令窗口中执行以下代码。如果需要,您可能需要更改路径和 jar 文件版本。
java - classpath "C:\Program Files\Foundation software Apache\ Tomcat 5.5\webapps\axis\WEB-INF\lib\axis.jar"; "C:\Program Files\Foundation software Apache\ Tomcat 5.5\webapps\axis\WEB-INF\lib\axis-ant.jar"; "C:\Program Files\Foundation software Apache\ Tomcat 5.5\webapps\axis\WEB-INF\lib\jaxrpc.jar"; "C:\Program Files\Foundation software Apache\ Tomcat 5.5\webapps\axis\WEB-INF\lib\commons,logging,1.0.4.jar"; "C:\Program Files\Foundation software Apache\ Tomcat 5.5\webapps\axis\WEB-INF\lib\commons,discovery,0.2.jar"; "C:\Program Files\Foundation software Apache\ Tomcat 5.5\webapps\axis\WEB-INF\lib\saaj.jar"; "C:\Program Files\Foundation software Apache\ Tomcat 5.5\webapps\axis\WEB-INF\lib\activation.jar" org.apache.axis.client.AdminClient deploy.wsdd
- 然后,在 Java 中构建以下两个类。第一个类将被命名为
WsOrderSummary
,它本身就是 Java 中的 Web 服务。将以下方法添加到您的wsOrderSummary
类中// The Axis Web Method public Document getOrderSummary(Document XMLdoc ) { try { NodeList XMLrows = XMLdoc.getElementsByTagName("row"); ClassOrderSummary array = new ClassOrderSummary[1]; // Adding one empty item for( int row=0; row < XMLrows.getLength() ; row++) { NodeList XMLcolumns = XMLrows.item( row ).getChildNodes(); // OrderId int orderId = Integer.parseInt (XMLcolumns.item(0).getTextContent().trim()); // unitPrice float unitPrice = Float.valueOf (XMLcolumns.item(2).getTextContent().trim()).floatValue(); // quantity int Quantity=Integer.parseInt (XMLcolumns.item(3).getTextContent().trim()); // Discount float Discount = Float.valueOf (XMLcolumns.item(4).getTextContent().trim()).floatValue(); // Total float Total = (unitPrice*Quantity)*( 1 - Discount); // Searching in the array int idx=existsOrder( array, orderId ); if( idx >= 0) { // found it! array[idx].OrderTotal += Total; } else { // if not exists, creates a new one array[array.length-1] = new ClassOrderSummary(); array[array.length-1].OrderID = orderId; array[array.length-1].OrderTotal = total; array=(ClassOrderSummary ) resizeArray( array, array.length + 1); } } array=(ClassOrderSummary ) resizeArray ( array, array.length -1); // Dropping last empty item //System.out.println ( array.length ); Document XMLResponse = createXMLOrders( array ); return(XMLResponse ); } catch(Exception ex ) { System.out.println ( " error:" + ex.getMessage ()); ex.printStackTrace (); return( null ); } }
第二个类将用于构建 XML SOAP 响应。这个类将被命名为
ClassOrderSummary
。参见ClassOrderSummary.java文件public class ClassOrderSummary { public int OrderID; public float OrderTotal; public ClassOrderSummary() { } }
- 在拥有两个 Java 文件后,使用 Java JDK 编译器编译它们。在 DOS 命令窗口中执行以下代码。不要忘记在必要时修改javac.exe路径文件,以及这两个 Java 类文件。
C:\Program Files\Java\jdk1.5.0_05\bin\javac.exe wsOrderSummary.java ClassOrderSummary.java
- 要完成部署,编译器会创建 2 个类文件,将这些文件复制到 axis 的类文件夹
C:\Program Files\Foundation software Apache\ Tomcat 5.5\webapps\axis\WEB-INF\classes
- 重新启动 Tomcat Apache 服务。通过打开 Web 浏览器访问以下 URL https://:8080/axis/services/wsOrderSummary?wsdl 来测试 Web 服务。如果 Web 服务不在您的本地主机上,请更改服务器名称。如果您有 IDE(eclipse、JDeveloper 等),IDE 将执行其中一个恢复步骤。
使用的 JAVA 工具 类型 版本 JRE 1.5.0.06 JDK 1.5.0.05 Apache Tomcat 5.5 Apache Axis 1.4
C# 客户端
要在 ASP.NET Framework 中发送 SOAP 消息,我们使用 WSE (Web Services Enhancements) 3.0。我们首先分析 Axis Web 服务发布的 SOAP 消息结构。
<?xml version="1.0" encoding="utf-8"?>
<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/"
xmlns:impl="https://:8080/axis/services/wsOrderSummary"
xmlns:apachesoap="http://xml.apache.org/xml-soap">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<impl:getOrderSummary>
<XMLdoc xsi:type="apachesoap:Document"></XMLdoc>
</impl:getOrderSummary>
</soap:Body>
</soap:Envelope>
有两个重要的命名空间,第一个是“xmlns:impl
”,它限定了此特定 Web 服务的命名空间,第二个是“xmlns:apachesoap
”,它标识了 Java 特殊类类型。在Body
内部是“impl:getOrderSummary
”方法,我们想调用它。在此方法内部有一个名为“XMLDoc
”的参数,它是一个“apachesoap:Document
”类型。它等同于 ASP.NET 中的XmlDocument
对象。
- 首先,创建一个控制台应用程序。之后,创建一个派生自
SoapClient
对象的类,以便访问其属性,并主要调用SendRequestResponse
方法,该方法允许发送和接收 SOAP 消息。它将被命名为ClassSoapClient
。public class ClassSoapClient : SoapClient { private String soapAction; public ClassSoapClient(string soapAction, EndpointReference ref1) : base(ref1) { this.soapAction = soapAction; } public SoapEnvelope SendEnvelope(XmlDocument xmlDoc) { SoapEnvelope soapRequest = new SoapEnvelope(); soapRequest.CreateBody(); soapRequest.Body.AppendChild (soapRequest.ImportNode(xmlDoc.DocumentElement, true)); return base.SendRequestResponse(soapAction, soapRequest); } }
请注意,
SendEnvelope
方法接收一个 XML 文档作为参数;它包含一个我们想要发送到 Java Web 服务的已序列化对象。它将 XML 文档插入到 SoapEnvelope(WSE 的一部分)类型的对象中。接下来,它调用SendRequestResponse
方法,该方法通过通常是 HTTP 的协议发送 SOAP 消息。SendRequestResponse
在收到响应消息或达到超时之前不会返回控制。然后,响应消息作为SoapEnvelope
对象再次返回。 - 接下来,更新
Program
类,该类位于Program.cs文件中,它是之前创建的控制台应用程序的一部分。static void Main( string args ) { Run(); }
在
Run
方法中,写入以下内容String _UrlWebService = "https://:8080/axis/services/wsOrderSummary"; // Change the web // service's URL here String _pathFiles = "C:\\NET_with_WS_AXIS\\DotNetClient\\Xml\\";// Change the XML // local path here int _minutes = 3;
“
_UrlWebservice
”是 Web 服务位置的 URL,“_pathFiles
”变量是发送 XML 的路径,以及我们保存从 Java Web 服务接收的 SOAP 消息的路径。创建ClassSoapClient
类的实例并将超时设置为 3 分钟,同时创建Address
对象,该对象表示 Web 服务将从中发送 SOAP 消息的 URL 对象。ClassSoapClient sc = new ClassSoapClient ("http ://inApacheAxisSoapActionDoesnotCare.org", // new Uri(_UrlWebService )); sc.Timeout = _minutes * 60000; sc.Destination.Address = new Microsoft.Web.Services3.Addressing.Address (new Uri(_UrlWebService));
- 接下来创建并加载要发送的 XML 文档。
XmlDocument docXML = new XmlDocument(); docXML.Load ( _pathFiles + " Orders.xml ");
有必要序列化我们要访问的 Web 服务的方法和参数。否则,
SendEnvelope
方法将不知道要访问哪个方法。它将所有这些加载到一个XmlDocument
对象中,并将包含订单采购信息的先前 XML 文档添加为方法的子参数。// This is the web service method and its parameter in xml format String soapString = "<impl:getOrderSummary xmlns: xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + " xmlns:impl=\"https://:8080/axis/services/wsOrderSummary\" >" + "<XMLdoc xsi:type=\"apachesoap:Document\" />" + "</impl:getOrderSummary>"; XmlDocument requestXML = new XmlDocument(); requestXML.LoadXml(soapString); requestXML.FirstChild.FirstChild.AppendChild(requestXML.ImportNode (docXML.DocumentElement, true));
- 最后,发送 SOAP 请求,该方法获得 SOAP 响应,SOAP 响应被保存到文件中以供以后分析。我们还提取“
ORDERS
”节点;它包含来自 Web 服务的响应。此时,我们可以将此 XML 文档反序列化为一个对象,例如将其加载到Dataset
对象中或将其保存到数据库中。SoapEnvelope soapResponse = new SoapEnvelope(); // Call Axis web service and get soap response soapResponse = sc.SendEnvelope(requestXML); // saving soap response soapResponse.Save(_pathFiles + "soapResponse.xml"); docXML.InnerXml = soapResponse.Body.GetElementsByTagName ("ORDERS")[0].ParentNode.InnerXml; // Finally we get orders summary XML ready for deserialize docXML.Save(_pathFiles + "OrdersSummary.xml");
.NET 工具使用 类型 版本 Microsoft.NET Framework 2.0 WSE 3.0 IDE Microsoft Visual C# 2005 Express Edition
历史
- 2007 年 8 月 2 日:初始发布