转自:http://www.cnblogs.com/qingyuan/archive/2012/05/23/2514566.html
学习 .NET 开发人员在 WCF 在璀璨的灯光下, Web Service 似乎要被遗忘了。因为当我身边的技术人员发声时 WCF 真是欺负人!废话不多。我已经很久没有写博客了。今天,我们来总结一下我这几天遇到的几件事 WebService 跨语言调用问题。
1 WebService 简介
Web Service 也叫 XML Web Service WebService 它是一种可以从 接收数据的设备 Internet 或者 Intranet 请求通过其他系统传递上,轻量级独立通信技术。是的 : 通过 SOAP 在 Web 提供的软件服务,使用 WSDL 文档描述和批准 UDDI 注册。
Web Service 以上就是介绍,大家都明白。网上的材料太多了,我以前做过 Web Service 程序员知道它的优点,并且以前从未研究过它 WS 程序员也知道它的优点,所以我不会在这里详细介绍。
参考文章 : http://baike.baidu.com/view/837392.htm
2 SOAP 消息结构
要学习 WebService 绝对需要了解 Soap 协议,它是 WebService 的基础。
SOAP ( Simple Object Access Protocol )简单对象访问协议,它基于 XML 消息传递协议使软件组件和基于服务的应用程序能够使用标准 HTTP 通信协议 (SOAP 是基于 HTTP 之上的 ) 。
SOAP 的消息文档是 XML 格式 化。相信大家都看过:

SOAP 主要是由 4 零件组成:
SOAP Envelope
这是 XML 的顶级元素,具有以下语法:
( 1 )元素名称为 Envelope 必须存在并且是根元素。
( 2 )此元素可以包含其他属性,例如命名空间和生命。如果出现其他属性,则必须使用命名空间修饰它们。
( 3 )此元素可以包含其他子元素,如果使用这些子元素,则它们必须具有命名空间修饰,并且必须遵循 SOAP Body 在元素之后,也就是说 Envelope 的直接子元素 Header 和 Body 必须安排在顶部。
SOAP Header
Header 应该是 Envelope 中的第一个子元素是可选的,语法规则如下所示:
( 1 )元素名称为 Header 没有必要存在,但如果存在,它必须是 SOAP Envelope 的第一个直接子元素。
( 2 ) Header 的所有直接子元素都是其 Item ,每个 Itemdoiu 必须具有命名空间修饰。
( 3 ) Header 的 Item 它还可以包含从属子元素,但这些子元素不是 Header 的 Item ,但相当具体 Item 的内容。
此外, SOAP encodingStyle 用于指定的属性 Header 条目的编码样式, mustUnderstand 属性和 actor 用于指定的属性如何处理 Item 谁来处理它。例如:
7
**SOAP Body**
SOAP Body 该元素为消息的最终接收者提供了一种简单的机制来交换信息。语法如下:
( 1 )元素名称为 Body ,必须在 SOAP 出现在邮件中,并且还必须 SOAP Envelope 的直接子元素,如果没有 Header ,则 Body 必须是第一个直接子元素;如果有的话 Header ,则 Body 必须紧跟 Header 元素存在。
( 2 )与 Header 相似,每个 Body 的 Item 所有这些都必须用命名空间装饰。另外 Body 中有个 SOAP Fault 元素,用于指示调用错误信息。
( 3 ) Body 的 Item 下面的子元素不是 Body 的 Item 了,而是 Item 的内容
**SOAP Fault**
用于在 SOAP 消息中的传输错误和状态信息。如果存在,则必须 Body 的一个 Item ,且 Body 只能出现一次 Fault 。 SOAP Fault 该元素具有以下子元素:
(1) faultcode 必须在 SOAP Fault 出现在元素中
(2)faultstring 此元素为这些错误代码提供用户可读的错误解释,并且未针对程序处理进行设置。
(3)faultactor 此元素描述消息路径中错误的发起方,类似于 SOAP actor 属性,但不是指示 Header 条目的收件人,而不是指示错误的来源。
(4) tail 此元件用于传输 Body 元素相关应用程序的错误消息
**3** **WebService 5** **种模式**
请求响应模式
fire-and-forget 模式
高级消息模式
增量解析和处理模式
缓存模式
**4** **WebService** **自定义** **SoapHeader** **安全验证**
SOAP 标头提供了一种将数据传递到 XML Web services 方法或从 XML Web services 传输数据的方法,前提是数据与 XML Web services 该方法的主要功能是相关的。例如,一个 XML Web services 可能包括几个 XML Web services 方法,并且每个方法都需要自定义身份验证方案。无需向需要自定义的每个身份验证方案添加参数 XML Web services 方法,可从 SoapHeader 派生类 [SoapHeaderAttribute](http://msdn.microsoft.com/zh-cn/library/system.web.services.protocols.soapheaderattribute%28v=vs.80%29.aspx) 适用于每个 XML Web services 方法。从 SoapHeader 派生类的实现处理此自定义身份验证方案。这样, XML Web services 方法使用 SOAP 标头仅实现其特定功能并添加其他功能。
以下列表提供了接收和处理的概述 SOAP 标头的基本步骤:
创建一个 SoapHeader 派生类,表示传入 SOAP 标头数据。
向实现添加成员 XML Web services 的类或 XML Web services 客户端代理类(它们属于在第一步中创建的类型)。
在 [MemberName](http://msdn.microsoft.com/zh-cn/library/system.web.services.protocols.soapheaderattribute.membername%28v=vs.80%29.aspx) 在属性中创建的成员将 SoapHeaderAttribute 应用于 XML Web services 方法或代理类中的相应方法。
在 XML Web services 方法或 XML Web services 在客户端代码中访问 MemberName 要处理的属性 SOAP 标头中发送的数据。
验证示例代码:
(1) 首先,定义自定义 SoapHeader

public class MyHeader:SoapHeader
{
public int ID { get ; set ; }
public string Name { get ; set ; }
public string PassWord { get ; set ; }
}

(2) 在 WebService 添加到公开的方法 SoapHeader 描述

[WebService(Namespace = " http://tempuri.org/ " )]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1\_1)]
[System.ComponentModel.ToolboxItem( false )]
public class Info : System.Web.Services.WebService
{
public SoapUnknownHeader[] unknownHeaders;
public MyHeader MyHeader { get ; set ; }
[WebMethod]
[SoapHeader( " unknownHeaders " )]
public string HelloWorld()
{
Console.WriteLine( " ?>>>>>>>>>>>>>>>>>>>> " );
return " Hello World " ;
}
[SoapHeader( " MyHeader " , Direction = SoapHeaderDirection.InOut)]
[WebMethod]
public string Audit()
{
Validate();
return " 这是验证 " ;
}
// 验证函数 自定义
private string Validate()
{
if (MyHeader != null )
{
if (MyHeader.Name == MyHeader.PassWord)
{
return " 验证通过 " ;
}
else
{
return " 验证失败 " ;
}
}
return " 邮件头未送达 " ;
}
}

这里的重点是公开服务的方法 public string Audit()
在WebService在 中定义类的属性 public MyHeader MyHeader { get ; set ; } 这就是我们定制的SOAPHeader同时,还需要Audit()将以下说明添加到该方法:
[SoapHeader( " MyHeader " , Direction = SoapHeaderDirection.InOut)]
如果客户端通过相应的SoapHeader此属性将用于接收消息,主功能描述中的参数应指向定义的属性名称。
(3) 客户端生存代理
众所周知,客户端生成的代理--右键--添加Web只需引用它,现在让我们来看看里面生成的代码
 MyHeader客户端生成的代理类
代理类中存在的相应属性,此类还继承SoapHeader类。

[System.Web.Services.Protocols.SoapHeaderAttribute( " MyHeaderValue " , Direction=System.Web.Services.Protocols.SoapHeaderDirection.InOut)]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute( " http://tempuri.org/Audit " , RequestNamespace= " http://tempuri.org/ " , ResponseNamespace= " http://tempuri.org/ " , Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string Audit() {
object [] results = this .Invoke( " Audit " , new object [ 0 ]);
return (( string )(results[ 0 ]));
}
public MyHeader MyHeaderValue {
get {
return this.myHeaderValueField;
}
set {
this.myHeaderValueField = value;
}
}

(4)客户端调用

MyService.Info info = new MyService.Info();
MyService.MyHeader myHeader = new MyService.MyHeader();
myHeader.ID = 1 ;
myHeader.Name = " qingyuan " ;
myHeader.PassWord = " qingyuan " ;
info.MyHeaderValue = myHeader;
string content= info.Audit();
Response.Write(content);

**5** **在不同语言之间通话**
在我们的工作中,很多时候我们会遇到这样的问题,有人说 Java 不能调用 .NET 写 WebService 。我没有骗他们,所以 WebService 跨平台不是开玩笑吗?其实不是那样的。我们这个时候真正应该研究的是 SOAP 我们自己的组件,我们可以使用 WSDL 来看看他们的不同之处。
.NET 生存的 WSDL 一部分

Java 生存的 WSDL 一部分

这是同一个SoapHeader生成的WSDL仔细观察,仍然存在差异java缺少一个form元素。 缺少此元素会导致.NET的序列化机制无法识别这一点xml文件。那么我们应该怎么做。
在.NET的自定义SoapHeader将以下说明添加到 的属性中
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
**6** **.NET** **从以下位置获得匿名性** **SoapHeader** **内容**
很多时候,当我们做事时,我们只是和孔雀玩游戏。当然,这不是讽刺,这是题外话!我们喜欢将我们自己的一些愿望和想法强加于它。
我有一个 WebService 在服务器端,现在客户端调用这个 WebService 当被迫提交 SOAPHeader 信息,希望 WebService 能够处理。在上面的部分中,我们可以发现客户提交了 SOAPHeader 当时,服务器有一个载体,因为我们在服务器上公开的方法中使用它 SOAPHeader 我已经描述了它,但现在服务器没有使用自定义 SOAPHeader 描述,并客户强行提交 SOAPHeader 我们该如何处理这个问题。
1 . 客户端定义了一个 SOAPHeader 自定义对象

public class MyInfo:SoapHeader
{
public MyInfo()
{
}
public int ID { get ; set ; }
public string Name { get ; set ; }
}

这是在客户端添加的SoapHeader 不要在服务器上添加此类
2 . 客户端代理方法添加 SOAPHeader 的描述

/* ***************************************************************** */
public MyInfo MyInfo { get ; set ; }
[SoapHeader( " MyInfo " , Direction = SoapHeaderDirection.InOut)]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute( " http://tempuri.org/HelloWorld " , RequestNamespace= " http://tempuri.org/ " , ResponseNamespace= " http://tempuri.org/ " , Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string HelloWorld() {
object [] results = this .Invoke( " HelloWorld " , new object [ 0 ]);
return (( string )(results[ 0 ]));
}
/* ***************************************************************** */

在这里,就像普通的代理方法一样,添加一个客户端SOAPHeader的描述
3. 在服务器上添加匿名性 SOAPHeader 的处理

public SoapUnknownHeader[] unknownHeaders;
[WebMethod]
[SoapHeader( " unknownHeaders " )]
public string HelloWorld()
{
Console.WriteLine( " ?>>>>>>>>>>>>>>>>>>>> " );
return " Hello World " ;
}

服务器需要使用SoapUnknownHeader接收匿名提交SoapHeader。因为服务器上没有对应的载体,暴露的方法需要添加相应的描述
4. 客户端调用

MyService.Info info = new MyService.Info();
MyInfo myInfo = new MyInfo();
myInfo.ID = 1 ;
myInfo.Name = " dddd " ;
info.MyInfo = myInfo;
string name = info.HelloWorld();
Response.Write(name);

在服务器上启动调试模式并跟踪提交的数据
从上图可以看出,数据已经传输完毕,并且xml设置数据格式,用于xml的解析在.NET在这里实现匿名并不难SoapHeader发送和接收消息
**7 JavaScript** **异步调用** **WebService**
参考: [http://www.cnblogs.com/qingyuan/archive/2009/12/09/1620405.html](http://www.cnblogs.com/qingyuan/archive/2009/12/09/1620405.html)
[http://www.cnblogs.com/jeffreyzhao/archive/2007/07/23/something\_about\_calling\_web\_service\_method.html](http://www.cnblogs.com/jeffreyzhao/archive/2007/07/23/something_about_calling_web_service_method.html)
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除