WCF光芒下的Web Service

学习.NET的开发人员,在WCF的光芒照耀下,Web Service 似乎快要被人遗忘了。因为身边做技术的人一开口就是WCF多么的牛逼!废话不多,本人很久不写博客,今天总结一下最近几日遇到的几个关于WebService 跨语言的调用问题。

 

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

 

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和由谁来处理。如:

<ENV:Header>

    <uniB2B:Priority MXLns:uniB2B="some-URI"

                     ENV:mustUnderstand="1">7</uniB2B:Priority>

</ENV:Header>

 

 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 应用于每个 XML Web services 方法。从 SoapHeader 派生的类的实现处理该自定义身份验证方案。按照此方式,XML Web services 方法使用 SOAP 标头来仅实现特定于它的功能并添加其他功能。

下面的列表概述接收和处理 SOAP 标头的基本步骤:

创建一个从 SoapHeader 派生的类,表示传入 SOAP 标头的数据。

将一个成员添加到实现 XML Web services 的类或 XML Web services 客户端代理类(它们属于在第一步创建的类型)。

指定第二步中在 MemberName 属性中创建的成员,将 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/jeffreyzhao/archive/2007/07/23/something_about_calling_web_service_method.html

 

 

时间: 2024-10-28 18:11:16

WCF光芒下的Web Service的相关文章

运用C#创建一个.Net下的Web Service

web|创建 微软在其.net战略中,对其主推的Web Service做了大肆的宣扬.现在,Web Service正如火如荼地发展着,相关的各项新技术层出不穷.Web Service的发展正构筑着互联网时代美好的明天.在本文中,我将向大家介绍Web Service的一些基本知识.如何用C#建立一个Web Service.通过文章,我们还将对WSDL.UDDI以及未来的Web Service有一个大致的了解. 为什么需要Web Service? 以前,分布式的应用程序逻辑需要使用分布式的对象模型,

WCF中引用其他Web Service部署IIS后调用报错

问题描述 在WCF中引用了其他WebService,本机测试一切正常,调用正常.发布部署IIS后,可以正常访问,其他方法也正常,调用这个引用了其他WebService的方法就报错.错误信息如下:Therewasnoendpointlisteningathttp://XX.XXXX:8899/sms_hb/services/Sms/thatcouldacceptthemessage.ThisisoftencausedbyanincorrectaddressorSOAPaction.SeeInner

什么情况下应该使用Web Service?

webservice 现在我将列举三种情况,在这三种情况下,你将会发现使用Web service会带来极大的好处.此后,我还会举出不应该使用Web service的一些情况. 跨越防火墙的通信 如果你的应用程序有成千上万的用户,而且他们都分布在世界各地,那么客户端和服务器之间的通信将是一个棘手的问题.那是因为客户端和服务器之间通常都会有防火墙或者代理服务器.在这种情况下,你想使用DCOM就不是那么简单了,而且,通常你也不愿意把你的客户端程序发布到如此庞大数量的每一个用户手中.于是,你最终选择了用

什么是Web Service

web 你可能早就听说过Web service了,你也可能已经对Web service有一些概念了.一时间,好像所有的计算机期刊.书籍和网站都开始提及Web service.然而,当前大多数对Web service的介绍都没能清楚的说明Web service到底是什么.他们只是鼓吹Web service是多么多么的好,简直就像是在做广告.在本文中会讲清楚两件事:Web service到底是什么:在什么情况下你应该使用Web service. 分布式应用程序和浏览器研究一下当前的应用程序开发,你会

什么时候应该使用Web Service【转,推荐】

web 现在我将列举三种情况,在这三种情况下,你将会发现使用Web service会带来极大的好处.此后,我还会举出不应该使用Web service的一些情况. 跨越防火墙的通信     如果你的应用程序有成千上万的用户,而且他们都分布在世界各地,那么客户端和服务器之间的通信将是一个棘手的问题.那是因为客户端和服务器之间通常都会有防火墙或者代理服务器.在这种情况下,你想使用DCOM就不是那么简单了,而且,通常你也不愿意把你的客户端程序发布到如此庞大数量的每一个用户手中.于是,你最终选择了用浏览器

Web Service学习总结

Web service到底是什么,在什么情况下你应该使用Web service:      研究一下当前的应用开发程序,你会发现一个绝对的倾向:人们开始偏爱基于浏览器的客户端应用程序.这当然不是因为客户端能够提供更好的用户界面,而是因为它能够避免花在桌面应用程序发布上的高成本.发布桌面应用程序成本很高,一半是因为应用程序安装和配置的问题,另一半是因为客户端和服务器之间通信的问题.      传统的Windows客户应用程序使用DCOM来与服务器进行通信和调用远程对象.配置好DCOM使其在一个大型

web service连接数据

问题描述 各位大大 小弟刚刚接触web service 想给个服务器端连接数据库查出结果集送给客户端,客户端接收后能打印出来的例子.用JAVA写 谢谢~~~~ 问题补充:我用的是cxf-dosgi来弄的 现在搞定了 原来要依赖数据库驱动的jar包 谢谢大家了 解决方案 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/sc

Java主流Web Service框架介绍:CXF和Axis2

CXF和Axis2是目前java平台上最主流的两个框架,虽然两个项目都隶属ASF,但却是基于不同思想和风格实现的,因此也各有所长.       CXF:http://cxf.apache.org/   是由过去的Celtix和XFire两个框架合并而来,CXF在java社区有广泛的接受度是得益于它能很好的集成Spring.我认为CXF最突出的两个优势是: 1.对JAX-WS规范的完整实现. 作为java平台上的WebService标准,过去既有的WebService产品必然会向这一标准靠拢,而J

WCF分布式开发必备知识(4):Web Service

今天继续我们的WCF分布式开发必备知识系列文章的第4节:Web Service.前3节我们分别介绍了MSMQ消息队列\.Net Remoting\Enterprise Services三个相关的技术.并且给详细注释的代码实现例子.先介绍一下本节的文章组织结构,首先还是介绍1.Web Service的基本概念2.优势和缺点3.使用Web Service的场合4.安全问题5.实现代码部分最后是总结.初学者就当入门资料,高手就当温习,也欢迎提出意见. 那现在我们就开始今天的学习,网上关于Web Ser