今天我们继续WCF分布式开发步步为赢(3)WCF服务元数据交换、配置及编程开发的学习。经过前面两节的学习,我们了解WCF分布式开发的相关的基本的概念和自定义宿主托管服务的完整的开发和配置过程。今天我们来详细学习WCF服务元数据交换的相关内容。WCF服务元数据究竟是什么?为什么WCF服务要暴露元数据交换节点?这些和以前的Web Service有什么关系?WCF服务元数据交换的方式有那些?我们如何实现WCF服务元数据交换,本节我们会详细讲解。全文结构如下:【1】WCF服务元数据的基本概念、【2】WCF服务元数据交换方式介绍【3】WCF服务元数据交换配置实现过程详解【4】WCF服务元数据交换编程实现过程详解【5】总结。

【1】WCF服务元数据的基本概念:

WCF服务元数据究竟是什么?它的作用是什么?为什么WCF服务要暴露元数据交换节点?这些和以前的Web Service有什么关系?这些通常是我们在学习WCF服务分布式系统开发过程中常常困扰我们的问题。

【1.1】WCF服务元数据是什么:

WCF服务元数据是WCF服务的核心部分服务地址(Address)、绑定(通信协议Binding)、契约(服务、操作、数据Contract)的原始描述信息。服务所公开的元数据包括 XSD(文档中出现的元素、文档中出现的属性、子元素、子元素的数量、子元素的顺序、元素是否为空、元素和属性的数据类型、元素或属性的默认和固定值)和 WSDL 文档(用于描述服务的方法、参数、参数个数、顺序、返回值、返回值的类型等方法的相关信息)。.Disco文档(描述服务的协议、地址、命名空间等信息)。

这些关键的WCF服务元数据全部都是基于XML语言描述,支持核心的行业标准协议。XSD好处显而易见,  基于XML,没有专门的语法 ,XML Schema支持一系列的数据类型(int、float、Boolean、date等) ,可扩充的数据模型,支持综合命名空间 ,支持属性组等。而这些正式WCF分布式服务追求的跨语言、跨平台的关键部分所在。

【1.2】为什么要暴露服务元数据:

知道了WCF服务元数据的概念后,我们就能理解为什么要暴露服务的元数据。WCF服务的元数据描述服务的核心信息,客户端需要了解这些特征以便与该服务进行通信。要想实现异构平台或者系统之间的通信,以前的技术是使用Web Service.因为其具有自描述、可扩展、与平台无关等优势。客户端只需要根据Web Service地址,便可获取服务的相关信息,反序列话本地的代码,通过服务代理进行服务的调用。

WCF服务主要特性之一就是跨平台的服务交互。而暴露服务元数据的重要原因就是解决了异构客户端服务交互的关键问题。 元数据基于XML,自描述。客户端可以根据服务的元数据反序列换生成本地代码,无论是c#,vb还是java语。

【1.3】WCF的服务和Web Service比较:

WCF其中一个重要特性就是支持Web Service的核心协议。无论是服务应用程序还是实际项目中客户端服务的引用的代码都能看出很多相似之处。这里线来看看服务程序的代码结构(IIS托管为例)。

两者除了包括自己的扩展文件外还有与其对应的服务代码文件。

再来看看客户端引用服务后本地的代码结构。首先是Web Service客户端的服务引用的本地文件:

其次是WCF客户端服务引用的文件结构:

两者都包括服务的本地代码文件(反序列化生成的本地服务相关代码),WSDL服务描述文件、XSD服务结构文件。WCF框架模型一定程度上参考了以前的ASP.NET Web Service,并对此进行了扩展。

【2】WCF服务元数据交换方式介绍:

WCF服务有两种方案可以发布自己的元数据。一种是基于HTTP-GET协议提供元数据;另一种则为MEX终结点元数据交换方式,和WCF服务一样使用一个专门的终结点,称为MEX元数据交换终结点。

System.ServiceModel.Description命名空间里MetadataExchangeClientMode枚举类型里进行了定义。代码如下:


using System;

namespace System.ServiceModel.Description
{
    // Summary:
    //     Specifies the exchange mode used to obtain metadata.
    public enum MetadataExchangeClientMode
    {
        // Summary:
        //     A WS-Transfer Get request is used.
        MetadataExchange = 0,
        //
        // Summary:
        //     An HTTP GET request is used.
        HttpGet = 1,
    }
}

元数据交换终结点与其它终结点相似,包含自己的地址(Address)、绑定(通信协议Binding)、契约(服务、操作、数据Contract),但是使用的服务契约为WCF提供的接口IMetadataExchange。两种发布元数据的方式使用了两种不同的标准网络传输协议,前者为HTTP/GET请求,后者为WS-MetadataExchange(MEX:WCF支持的基本绑定HTTP、HTTPS、TCP、IPC等绑定协议)。

启用元数据交换服务后,必须显式配置元数据交换行为。下面我们来分别详细介绍WCF服务元数据交换配置和编程两种方式的实现过程。

【3】WCF服务元数据交换配置实现过程详解:

【3.1】配置HTTP-GET元数据交换方式:

需要配置服务的行为和基地址,客户端可以根据基地址查看服务的元数据。代码如下:


      <service name="WcfServiceApp.WCFService" behaviorConfiguration="WcfServiceApp.WCFServiceBehavior">
                <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8001/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfServiceApp.WCFServiceBehavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

配置完成以后,我们可以使用基地址在浏览器里查看服务的信息,效果如下图:

【3.2】配置终结点元数据交换方式:

我们这里配置了3种方式的元数据交换终结点,分别是HTTP、TCP、IPC方式。具体代码如下:


<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
        <endpoint address="mex" binding="mexNamedPipeBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8001/"/>
            <add baseAddress="net.tcp://localhost:8002/"/>
            <add baseAddress="net.pipe://localhost/"/>
          </baseAddresses>
        </host>
服务行为:
<serviceBehaviors>
        <behavior name="WCFService.WCFServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

【4】WCF服务元数据交换编程实现过程详解:

以上的配置文件实现的WCF服务的元数据交换,同样我们也可以通过编程方式实现。前者配置简单、快捷,后者相对复杂。但是编程方式允许代码运行时控制或者设置元数据交换的信息。因而更加灵活。下面我们就来看看如何通过代码实现刚才的服务原数据交换的配置。

【4.1】WCF服务元数据交换HTTP-GET编程实现:

必须添加对命名空间的引用, using System.ServiceModel.Description;我们对服务元数据操作的类和接口信息定义在此命名空间里,具体的实现HTTP-GET的代码如下:


 ServiceMetadataBehavior metadataBehavior;//定义服务行为变量,
                metadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
                //获取宿主的行为列表
                if (metadataBehavior == null)//如果没有服务原数据交换的行为,实例化添加服务原数据交换行为
                {
                    metadataBehavior = new ServiceMetadataBehavior();
                    Uri httpAddress = new Uri("http://localhost:8001/");
                    metadataBehavior.HttpGetUrl =httpAddress;
                    metadataBehavior.HttpGetEnabled = true;//设置HTTP方式
                    host.Description.Behaviors.Add(metadataBehavior);
                }

首先是获得服务行为的列表信息,如果没有设置,我们就进行实例化服务原数据交换行为,并设置http方式可用。 host.Description.Behaviors.Add(metadataBehavior);添加宿主服务的行为。

【4.2】WCF服务元数据交换WS-*编程实现:

这里分别实现了HTTP、TCP、IPC三种方式的的元数据交换的代码。和http-get方式略有不同,我们需要实例化自己绑定元素和绑定,最后作为参数传递给host宿主实例。具体实现代码如下:


//2编程方式实现ws*原数据交换
                //生命三个绑定节点类
                BindingElement tcpBindingElement = new TcpTransportBindingElement();
                BindingElement httpBindingElement = new HttpsTransportBindingElement();
                BindingElement pipeBindingElement = new NamedPipeTransportBindingElement();
                //实例化通用绑定类的实例
                Binding tcpBinding = new CustomBinding(tcpBindingElement);
                Binding httpBinding = new CustomBinding(httpBindingElement);
                Binding pipeBinding = new CustomBinding(pipeBindingElement);
                //
                Uri tcpBaseAddress = new Uri("net.tcp://localhost:9001/");
                Uri httpBaseAddress = new Uri("http://localhost:9002/");
                Uri pipeBaseAddress = new Uri("net.pipe://localhost/");
                host.AddServiceEndpoint(typeof(WCFService.IWCFService), new NetTcpBinding(), tcpBaseAddress);
                host.AddServiceEndpoint(typeof(WCFService.IWCFService), new WSHttpBinding(), httpBaseAddress);
                host.AddServiceEndpoint(typeof(WCFService.IWCFService), new NetNamedPipeBinding(), pipeBaseAddress);
                
                //ServiceMetadataBehavior metadataBehavior;//定义服务行为变量,
                metadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
                //获取宿主的行为列表
                if (metadataBehavior == null)//如果没有服务原数据交换的行为,实例化添加服务原数据交换行为
                {
                    metadataBehavior = new ServiceMetadataBehavior();                     host.Description.Behaviors.Add(metadataBehavior);
                }
                //如果没有可用的mex节点,可以使用一下代码判断,添加mex节点
                
                host.AddServiceEndpoint(typeof(IMetadataExchange), tcpBinding, "mex");
                host.AddServiceEndpoint(typeof(IMetadataExchange), httpBinding, "mex");
                host.AddServiceEndpoint(typeof(IMetadataExchange), pipeBinding, "mex");

【5】总结:

运行宿主程序,客户端添加服务引用,使用不同元数据地址,我们可以查询到不同的服务信息。结果如下:

【5.1】http-get方式:

【5.1】终结点http方式:

【5.1】终结点tcp方式:

【5.1】终结点ipc方式:

【5.5】结论

以上就是全部是WCF服务元数据交换相关概念、配置和编程实现http-get及WS-*等协议进行元数据交换的详细内容。元数据的信息除了包括服务、数据、操作等契约的相关的信息外,还有其他的如事物、可靠性、错误处理等相关的信息。

了解了这些实现过程之后,在实际的WCF服务项目中,我们就可以以不同的方式配置元数据交换方式。WCF元数据交换其实和Web Service原数据交换有类似之处,都是基于XML语言描述,原数据交换之所以这样重要。

首先,基于XML的元数据可以实现跨语言、跨平台之间的服务交互,真正做到与平台的无关性。

其次,通过原数据反序列化生成本地代理类等信息,因为这样就实现了真正的客户端和服务端的解耦,降低了系统之间的耦合度。传统的程序集引用方式无法降低系统的耦合度,这个也是我们系统设计追求的目标。

以上就是WCF服务元数据交互的全部内容,下面上传本节的实例代码:

/Files/frank_xl/WCFServiceMEXFrankXuLei.rar。供大家参考,也欢迎留言讨论~

WCF分布式开发步步为赢(3)WCF服务元数据交换、配置及编程开发的更多相关文章

  1. WCF分布式开发步步为赢(4):WCF服务可靠性传输配置与编程开发

    今天继续WCF分布式开发步步为赢系列的第4节:WCF服务可靠性传输配置与编程开发.这个章节,我们要介绍什么是WCF服务的可靠性传输,随便介绍网络协议的概念,Web Service为什么不支持可靠性传出 ...

  2. WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ

    之前曾经写过一个关于MSMQ消息队列的文章:WCF分布式开发必备知识(1):MSMQ消息队列 ,当时的目的也是用它来作为学习WCF 消息队列MSMQ编程的基础文章.在那篇文章里,我们详细介绍了MSMQ ...

  3. WCF分布式开发步步为赢(7):WCF数据契约与序列化

    本节继续学习WCF分布式开发步步为赢(7):WCF数据契约与序列化.数据契约是WCF应用程序开发中一个重要的概念,毫无疑问实现客户端与服务端数据契约的传递中序列化是非常重要的步骤.那么序列化是什么?为 ...

  4. WCF分布式开发步步为赢(9):WCF服务实例激活类型编程与开发

    .Net Remoting的激活方式也有三种:SingleTon模式.SingleCall模式.客户端激活方式,WCF服务实例激活类型包括三种方式:单调服务(Call Service),会话服务(Se ...

  5. WCF分布式开发步步为赢(11):WCF流处理(Streaming)机制

    WSE3.0框架提供了数据优化传输机制,WSE3.0构建Web服务安全(4):MTOM消息传输优化和文件上传.下载 疑问里进行了介绍.WCF同样也提供了流操作来支持大数据对象的传输和处理优化机制,今天 ...

  6. WCF分布式开发步步为赢(12):WCF事务机制(Transaction)和分布式事务编程

    今天我们继续学习WCF分布式开发步步为赢系列的12节:WCF事务机制(Transaction)和分布式事务编程.众所周知,应用系统开发过程中,事务是一个重要的概念.它是保证数据与服务可靠性的重要机制. ...

  7. WCF分布式开发步步为赢(14):WCF安全编程--基本概念

    WCF安全机制是个非常复杂的问题,因为涉及的知识点较多,所以今天这个文章,会分析进行WCF安全开发应该了解的哪些知识点.如何查看资料.为了更好地理解WCF安全相关知识,我把WCF安全机制主要知识点整理 ...

  8. HDD线上沙龙·创新开发专场:多元服务融合,助力应用创新开发

    5月24日,由华为开发者联盟主办的HUAWEI Developer Day(华为开发者日,简称HDD)线上沙龙·创新开发专场在华为开发者学堂及各大直播平台与广大开发者见面.直播内容主要聚焦Harmon ...

  9. [Intel Edison开发板] 06、Edison开发在linux中烧写、配置、搭建开发环境

    1.前言 linux上烧写.配置.搭建Edison环境,千万不要用默认的setup tool for ubuntu!!! (即使,你用的就是ubuntu) 因为,其默认的工具会从一个坏链接下载配置文件 ...

随机推荐

  1. core java 7 exception

    MODULE 7 Exceptions---------------------------- 程序正常执行过程中遇到的意外情况 引发异常的因素: 1)程序本身的内在因素 2)外部因素引发的,程序无须 ...

  2. JVM学习总结三——垃圾回收器

    整两天再看调优分析的部分,发现实际运行环境下,还是要考虑配置垃圾回收器,所以这里就加一小章介绍一下. 首先来看一下HotSpot所支持回收期的关系图: 图中可以看到一共有7中垃圾回收器,以中间绿线为界 ...

  3. 在线调试js工具网站

    http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/highch ...

  4. 混合使用C和C++

    C++作为C语言的扩展集,几乎所有的C程序都可以在C++中编译和运行,但是要注意C程序中可能使用了C++中的关键字作为变量,比如在C中:int class = 0; 但这在C++中不行.出于方便性,我 ...

  5. 部署报表和 ReportViewer 控件 rdlc

    部署报表和 ReportViewer 控件 您可以将报表和 ReportViewer 控件作为应用程序的一部分自由发布.根据控件类型以及报表是配置为本地处理还是远程处理,部署要求会有很大不同.在同一个 ...

  6. c++中的virtual函数,即虚函数

    c++中的虚函数主要是用来实现多态的,虽然都同时指向父类的实例.但调用的确实子类的函数,这个有点像java的接口和实现的关系了.一个接口有多种实现,一个接口对象调用的是哪个实现的方法,这个就是多态了 ...

  7. 【每日scrum】5.3

    团队的Backlog 初期总目标:完成需求分析,做好软件前期的一切准备. 任务 认领人 估算完成时间 查找铁大离线电子地图 验证地图的准确性 万彤 司新红 3天 接口需求 (用户界面和软件接口等) 曹 ...

  8. 二、freemarker.controller半自动静态化+Tomcat虚拟资源映射

    描述:本内容主要是讲2个tomcat之间同时共享一个静态话页面,统一入口是springMVC的一个controller,静态化的更新只需要传false.true.把完成的web项目放入a.b服务器To ...

  9. 反向Ajax,第2部分:WebSocket

    转自:http://kb.cnblogs.com/page/112616/ 前言 时至今日,用户期待的是可通过web访问快速.动态的应用.这一文章系列展示了如何使用反向Ajax(Reverse Aja ...

  10. C#格式化JSON字符串

    很多时候我们需要将json字符串以 {     "status": 1,     "sum": 9 }这种方式显示,而从服务端取回来的时候往往是这样 {&quo ...