WCF光芒下的WebService

原创
小哥 2年前 (2023-05-22) 阅读数 41 #大杂烩

转自: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 ![](http://common.cnblogs.com/images/copycode.gif) public class MyHeader:SoapHeader { public int ID { get ; set ; } public string Name { get ; set ; } public string PassWord { get ; set ; } } ![](http://common.cnblogs.com/images/copycode.gif) (2) 在 WebService 添加到公开的方法 SoapHeader 描述 ![](http://common.cnblogs.com/images/copycode.gif) [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 " 邮件头未送达 " ; } } ![](http://common.cnblogs.com/images/copycode.gif) 这里的重点是公开服务的方法 public string Audit() 在WebService在 中定义类的属性 public MyHeader MyHeader { get ; set ; } 这就是我们定制的SOAPHeader同时,还需要Audit()将以下说明添加到该方法: [SoapHeader( " MyHeader " , Direction = SoapHeaderDirection.InOut)] 如果客户端通过相应的SoapHeader此属性将用于接收消息,主功能描述中的参数应指向定义的属性名称。 (3) 客户端生存代理 众所周知,客户端生成的代理--右键--添加Web只需引用它,现在让我们来看看里面生成的代码 ![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif) MyHeader客户端生成的代理类 代理类中存在的相应属性,此类还继承SoapHeader类。 ![](http://common.cnblogs.com/images/copycode.gif) [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; } } ![](http://common.cnblogs.com/images/copycode.gif) (4)客户端调用 ![](http://common.cnblogs.com/images/copycode.gif) 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); ![](http://common.cnblogs.com/images/copycode.gif) **5** **在不同语言之间通话** 在我们的工作中,很多时候我们会遇到这样的问题,有人说 Java 不能调用 .NET 写 WebService 。我没有骗他们,所以 WebService 跨平台不是开玩笑吗?其实不是那样的。我们这个时候真正应该研究的是 SOAP 我们自己的组件,我们可以使用 WSDL 来看看他们的不同之处。 .NET 生存的 WSDL 一部分 ![](http://images.cnblogs.com/cnblogs_com/qingyuan/20120523002.jpg) Java 生存的 WSDL 一部分 ![](http://images.cnblogs.com/cnblogs_com/qingyuan/20120523003.jpg) 这是同一个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 自定义对象 ![](http://common.cnblogs.com/images/copycode.gif) public class MyInfo:SoapHeader { public MyInfo() { } public int ID { get ; set ; } public string Name { get ; set ; } } ![](http://common.cnblogs.com/images/copycode.gif) 这是在客户端添加的SoapHeader 不要在服务器上添加此类 2 . 客户端代理方法添加 SOAPHeader 的描述 ![](http://common.cnblogs.com/images/copycode.gif) /* ***************************************************************** */ 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 ])); } /* ***************************************************************** */ ![](http://common.cnblogs.com/images/copycode.gif) 在这里,就像普通的代理方法一样,添加一个客户端SOAPHeader的描述 3. 在服务器上添加匿名性 SOAPHeader 的处理 ![](http://common.cnblogs.com/images/copycode.gif) public SoapUnknownHeader[] unknownHeaders; [WebMethod] [SoapHeader( " unknownHeaders " )] public string HelloWorld() { Console.WriteLine( " ?>>>>>>>>>>>>>>>>>>>> " ); return " Hello World " ; } ![](http://common.cnblogs.com/images/copycode.gif) 服务器需要使用SoapUnknownHeader接收匿名提交SoapHeader。因为服务器上没有对应的载体,暴露的方法需要添加相应的描述 4. 客户端调用 ![](http://common.cnblogs.com/images/copycode.gif) 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); ![](http://common.cnblogs.com/images/copycode.gif) 在服务器上启动调试模式并跟踪提交的数据 ![](http://images.cnblogs.com/cnblogs_com/qingyuan/20120523004.jpg)从上图可以看出,数据已经传输完毕,并且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)
版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门