WCF (Windows Communication Foundation) Create & Implement a WCF Service

一个WCF 程序通常包含三个部分,WCF Service 程序集, WCF Service Host 程序集, WCF Client 程序集。

WCF Service 程序集:实现此WCF服务主要功能的程序集合。

WCF Service Host 程序集:一个可执行文件或是一个服务,能够运行在系统中,作为WCF Service的载体。

WCF Client 程序集:通过Proxy可以和WCF Service通信,并获取服务的应用程序。


over_view_dia


创建一个WCF应用程序一共需要5个步骤:

Defining Service Contract

Implementing Service Contract

Configuring Service EndPoints (Option)

Hosting Service in an Application

Building a Client Application


使用 Visual Studio 2010 创建 WCF

创建工程,其中可以使用WCF Service Library 和 WCF Service Application 来创建自己WCF 应用程序。

WCF Service Library:不包含WCF Host Application,仅是一个WCF Service简单的库,可以被包含到其他任意的Host中。

WCF Service Application:工程中包含了WCF Hosting Application,创建后可以直接使用。

cstep1_dia


可以有2种方法来实现WCF Service,仅 使用代码 代码+配置文件。这两种方式其实主要指的是描述WCF Service对外接口的信息。

例如定义WCF Service Endpoints 的地址,绑定信息,服务合约等,我们可以用代码来直接定义,也可以把这些信息放到配置文件中,这样当信息改变时无需重新编译代码。


方式 一:直接使用代码

创建WCF Service 程序时一定要使用 namespace: using System.ServiceModel;

关键字  [ServiceContract]:描述服务的类型

关键字  [OperationContract]:描述服务的接口

关键字  [DataContract]:描述服务的数据


应用实例:

Step 1:定义并实现Service 的接口(对应上述 5个步骤中的 1 和 2)

其中定义了一个WCF Service 的一个接口 AddTax 并且 类 AddTaxService 继承并实现了这个接口。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace AddTaxServiceLib
{
    [ServiceContract]
    public interface IAddTax
    {
        [OperationContract]
        decimal AddTax(decimal productCost, double taxRate);
    }

    public class AddTaxService : IAddTax
    {
        public decimal AddTax(decimal productCost, double taxRate)
        {
            return productCost + (productCost * (decimal)taxRate);
        }
    }
}

Step 2:创建一个WCF Service Host(对应上述 5个步骤中的 3 和 4)

这里的WCF Service Host Application 就是一个简单的控制台应用程序。这里又创建了一个WCF Service Host 的工程。


创建好工程后别忘记在Reference中加入System.ServiceModel 和 WCF Service 的Lib。

sln_info_dia


在Host 程序中分别定义 address,binding 和 contract。

address: 是client 用来和 host通信的地址

            Uri address = new Uri("http://localhost:8080/AddTaxService");
            myServiceHost = new ServiceHost(typeof(AddTaxService), address);

binding:   用来描述Endpoint的通信的channel,它至少包括了网络适配层的channel,但也可以配置一些其他的 channel,例如加密等。

                     WCF 库中提供了一些预定义的channel (BasicHttpBinding,WsHttpBinding,NetTcpBinding),基本上从名字也可以猜出其含义了,基于不同的网络协议。

            BasicHttpBinding binding = new BasicHttpBinding();

contract:  描述WCF Service服务接口信息。

            Type contract =  typeof(IAddTax)

定义好了 address, binding 和contract 后我们就可以添加Endpoint了。

            myServiceHost.AddServiceEndpoint(contract, binding, address);

我们虽然定义好了一个Endpoint, 但这时候Client端还没有任何Service端的信息,也就无法和Service端进行通信。

这时候就需要Service端提供一组元数据(Metadata)来描述Service的信息,并且提供给Client端。

这个过程则是通过 MEX endpoint 来实现的,它也是一个endpoint,与客户自定义的endpoint的不同在于它的功能就是向Client提供Service 的信息帮助Client与Service实现通信。

步骤 1:当Client 想与Service端进行通信时,它首先会与Service端的MEX Endpoint 进行通信

步骤 2:Service端的MEX Endpoint 会通过 Web Service Definition Language (WSDL) 把Service端的信息发送到Client 端

步骤 3:Client根据Service端的信息创建 Proxy 和 Configuration File,来与 Service端进行通信。


metadata_dia

在Service代码中添加 MEX Endpoint 首先 添加一个behavior

别忘了使用 namespace : using System.ServiceModel.Description;

            // Adding Service Metadata behavior
            ServiceMetadataBehavior mexbehavior = new ServiceMetadataBehavior();
            mexbehavior.HttpGetEnabled = true;
            myServiceHost.Description.Behaviors.Add(mexbehavior);

然后添加 MEX Endpoint 的 address binding 和 contract

例子中添加了一地址为 http://localhost:8080/AddTaxService/mex 的MEX Endpoint, 通过Http 协议进行通信

            //Adding Metadata behavior
            ServiceMetadataBehavior mexbehavior = new ServiceMetadataBehavior();
            mexbehavior.HttpGetEnabled = true;
            myServiceHost.Description.Behaviors.Add(mexbehavior);

            myServiceHost.AddServiceEndpoint(typeof(IMetadataExchange),
                                             MetadataExchangeBindings.CreateMexHttpBinding(),
                                             "mex");


实例代码下载:使用代码实现的 WCF Service Application。


方式 二:使用代码 + 配置文件

根据上述说明的实现WCF Application的5个步骤,首先还是要定义并实现WCF Service。

这步与方式一中的实现方法是一致的,不在赘述。

其次是实现一个 WCF Host Application,这里与上个例子中有所不同,基本不需要配置任何的Endpoint 信息和MEX Endpoint信息。这些信息将全部放入在配置文件中。

Host 的实例代码:可以看到其中没有配置任何关于Endpoint和 address, binding,还有 contract的信息。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using AddTaxServiceLib;

namespace TestServiceHost
{
    static class AddTaxServiceHost
    {
        private static ServiceHost myServiceHost;

        static void Main(string[] args)
        {
            myServiceHost = new ServiceHost(typeof(AddTaxService));
            myServiceHost.Open();
            Console.WriteLine("Press <enter> to termintered WCF service");
            Console.ReadLine();

            myServiceHost.Close();
        }
    }
}

配置文件写法:

配置文件包括一个<system.serviceModel> Node,  在它下面又包含了<services>,<bindings> , <behaviors>, <hosts>,<endpoints>,<clients>等节点。

下面是一个该例子中XML配置文件的例子 FileName: App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <system.serviceModel>
    <services>
      <service name="AddTaxServiceLib.AddTaxService"
               behaviorConfiguration="AddTaxServiceBehavior">
        <host>
          <baseAddresses> <add baseAddress = "http://localhost:8080/AddTaxService" /> </baseAddresses>
        </host>
        
        <!-- Service Endpoints -->
        <endpoint address ="" binding="basicHttpBinding" contract="AddTaxServiceLib.IAddTax"> </endpoint>

        <!-- Metadata Endpoints -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        
      </service>
    </services>
    
    <behaviors>
      <serviceBehaviors>
        <behavior name="AddTaxServiceBehavior">
             <serviceMetadata httpGetEnabled="True"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

</configuration>

与代码实现的WCF例子相比较,可以很容易理解该配置文件中的内容。


关于默认的Endpoint

在WCF 4中,它不会抛出任何异常,即使WCF Service没有配置任何的Endpoint,系统也会使用默认的EndPoint来进行处理。当然结果肯定不会是Client所希望的。

WCF 4 中定义了一个 public 方法 AddDefaultEndPoints,用户可以直接使用来添加默认的EndPoint。该方法为每个base address添加一个默认的EndPoint。

假设WCF Service定义了三个 Service Contract,但只配置了一个Base Address,在这种情况下,AddDefaultEndPoint会添加三个默认的 EndPoint。

再例如,假设WCF Service定义了二个 Service Contract,配置了两个Base Address,在这种情况下,AddDefaultEndPoint会添加四个默认的 EndPoint。

def_endpoint_dia


例如代码:Service 中有2个接口:IWelcome 和 IAddTax。

情形 1: 其中并没有添加 Endpoint 的代码。

class Program
{
    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(WelcomeToAddTasService),
                                           new Uri("http://localhost:8080/WelcomeToAddTasServcie"),
                                           new Uri("net.tcp://localhost:8081/WelcomeToAddTasServcie"));

        host.Open();
        foreach(SercideEndPoint se in host.Descritpion.Endpoints)
            Console.WriteLine("A: {0}, B: {1}, C: {2}", se.Address, se.Binding.Name, se.Contract.Name);

        Console.WriteLine("Press <Enter> to stop the service");
        Console.ReadLine();
        host.Close();
    }
}

可以看到,系统默认添加了4个EndPoint

def_diam


情形 2: 主动添加了 EndPoint。


class Program
{
    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(WelcomeToAddTasService),
                                           new Uri("http://localhost:8080/WelcomeToAddTasServcie"),
                                           new Uri("net.tcp://localhost:8081/WelcomeToAddTasServcie"));

        host.AddServiceEndpoint(typeof(IWelcome), new WSHttpBinding(), "myendpoint");
        host.Open();
        foreach(SercideEndPoint se in host.Descritpion.Endpoints)
            Console.WriteLine("A: {0}, B: {1}, C: {2}", se.Address, se.Binding.Name, se.Contract.Name);

        Console.WriteLine("Press <Enter> to stop the service");
        Console.ReadLine();
        host.Close();
    }
}

此时系统不会添加任何的默认的EndPoint.

manu_diag


情形 3: 主动添加了 EndPoint,并且掉用了 AddDefaultEndpoints 函数

class Program
{
    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(WelcomeToAddTasService),
                                           new Uri("http://localhost:8080/WelcomeToAddTasServcie"),
                                           new Uri("net.tcp://localhost:8081/WelcomeToAddTasServcie"));

        host.AddServiceEndpoint(typeof(IWelcome), new WSHttpBinding(), "myendpoint")
        host.AddDefaultEndpoints();
        host.Open();
        foreach(SercideEndPoint se in host.Descritpion.Endpoints)
            Console.WriteLine("A: {0}, B: {1}, C: {2}", se.Address, se.Binding.Name, se.Contract.Name);

        Console.WriteLine("Press <Enter> to stop the service");
        Console.ReadLine();
        host.Close();
    }
}


此时,系统将会把所有的默认的EndPoint 和用户自己添加的Endpoint 都加入到系统中

m_and_def_ep_diam


WCF4 中当然定义了一套默认的 Endpoint和传输协议对应关系的配置信息。当调用 AddDefaultEndponts方法时,系统可以通过这些配置信息找到 binding的方式。

文件:machine.config.comments 中定义如下:

<System.ServiceModel>
    <ProtocolMapping>
        <add scheme="http"      binding="basicHttpBinding"     bindingConfiguration=""/>

        <add scheme="net.tcp"   binding="netTcppBinding"       bindingConfiguration=""/>

        <add scheme="net.pipe"  binding="netNamedPipeBinding"  bindingConfiguration=""/>

        <add scheme="net.msmq"  binding="netMsmqBinding"       bindingConfiguration=""/>
    </ProtocolMapping>



关于标准的 Endpoint

WCF 同时还定义了一些标准的 Endpoint。(MEXEndpoint,   DynamicEndpoint,   discoveryEndpoint)

stand_ep_diam


使用Standard Endpoint只需要指定他们的名字就可以了。

例如:

<configuration>
    <system.serviceModel>
        <services>

        <endpoint kind="basicHttpBinding" contract="IWelcome"/>

        <endpoint kind="mexEndpoint"      address="mex"/>

        </services>
    </system.serviceModel>
</configuration>


实例代码下载:使用配置文件实现的WCF Service Application。


下一篇将继续介绍 WCF 的 Client 端。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值