WCF服务模型-阿里云开发者社区

开发者社区> 开发与运维> 正文

WCF服务模型

简介:

WCF服务模型语言的主要术语和WSDL的主要术语有紧密的对应关系。在WSDL中,对应于网络上通信的软件称为服务。服务通过XML文档进行描述,这些文档主要由三个部分组成:

1. 服务部分说明服务位于何处。

2. 绑定部分说明服务所能理解的标准通信协议。

3. portType部分列出服务所能提供的所有操作,它定义了服务根据接收的消息所发出的响应消息。

这样,WSDL的三个主要部分能告诉你服务的位置、如何与之通信,及它能做什么。

这三个部分恰好正是使用WCF服务模型服务时所需确定的:服务的位置、如何与之通信及它能做什么。在WSDL中分别称它们为服务、绑定和portType,在WCF模型中它们分别被称为地址(address)、绑定(binding)、契约(contract)。所以,a、b、c可作为WCF服务模型的三个主要术语的缩写。

更确切地说,在WCF服务模型中,对应通信功能的软件称为服务。服务具有一个或多个终结点(endpoint),通信会被定向到这些终结点。终结点由地址、绑定和契约组成。在终结点定义外部接口后,服务在内部如何处理通信是由一组称为行为(behavior)的控件点(control point)所决定的。

开发者首先从定义契约开始,这个步骤只需编写一个接口,并为接口和其一个或多个方法添加一些服务模型提供的特性,将接口指定为WCF的契约:

[ServiceContract]
public interface IEcho
{
[OperationContract]
string Echo(string input);
}

下一步是契约的实现

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class Service : IEcho
{
public string Echo(string input)
{
return input;
}
}

一个类如果实现了被指定为WCF契约的接口,它就称为服务类型(service type)。开发者应通过ServiceBehavior特性告诉WCF如何把从终结点接收到的数据传送给服务类型。上例中,该特性表示WCF传送数据给服务类型时是否可以使用多条并发线程。

开发者的最后一步即是将服务承载(host)在一个应用程序域(application domain)中。IIS和其他任何.NET程序都可以为承载服务提供应用程序域。只要使用WCF模型提供的ServiceHost类,就可很容易地将服务承载在任意的.NET程序中

using(ServiceHost host = new ServiceHost(typeof(Service))
{
host.Open();

Console.WriteLine("The service is ready.");
Console.ReadKey(true);

host.Close();
}

下一步应该管理员接手了。管理员通过将一个地址和绑定与服务类型所实现的WCF契约相关联,为服务类型定义一个终结点。WCF提供了一个称为Service Configuration Editor(服务配置编辑器)的编辑工具来完成这个任务(在 C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin 文件夹中可以找到服务配置编辑器。http://msdn.microsoft.com/zh-cn/vbasic/ms732009.aspx,http://www.cnblogs.com/pdfw/articles/1014265.html)

再下来,终结点的地址、绑定和契约都定义好,契约也实现了,服务的宿主环境也已提供,服务就可以使用了。在管理员运行宿主程序后,WCF会检查服务模型语言所定义的终结点地址、绑定、契约及行为,然后生成必要的组件以便服务可以接收和响应来自信道层的通信。

管理员可以控制服务是否向外发部描述其终结点的WSDL,如果选择发布,WCF会自动生成相应的WSDL并向需要它的请求返回该WSDL。开发人员可下载相应的WSDL,然后生成能与服务交换数据的代码及描述终结点信息的应用配置文件。这些操作只需一条命令即可完成:

svcutil http://localhost:8000/EchoService?wsdl

其中,svcutil是WCF的服务模型元数据工具(Service Model Metadata Tool),http://localhost:8000/EchoService?wsdl是服务元数据的下载地址。在使用该工具产生必要的代码和配置信息后,开发者就可利用它们和服务通信了。

using(EchoProxy echoProxy = new EchoProxy())
{
echoProxy.Open();
string response = echoProxy.Echo("Hello, World!");
echoProxy.Close();
}

前面给出的这些步骤就是使用WCF所需的所有步骤。总结一下,这些简单的步骤如下:

1. 服务开发者使用.NET接口定义一份契约。

2. 服务开发者编写一个实现该接口的类,即服务类型。

3. 服务开发者通过给服务类型及其方法添加特性WCF行为做出适当的修改。

4. 服务开发者为服务提供恰当的运行宿主环境。如果服务需要承载在一个.NET程序中,开发者应先开发此程序。

5. 服务管理员使用Service Configuration Editor配置服务的终结点,即为已被服务类型实现的契约关联地址和绑定。

6. 服务管理员使用Service Configuration Editor对WCF行为做出恰当的修改。

7. 客户程序的开发者使用服务模型元数据工具下载描述服务的WSDL并生成与服务通信所需的代码和配置文件。

8. 客户程序的开发者利用生成的代码和配置文件与服务通信。

注意:服务类型不只是实现了服务契约接口的类,那些直接添加了ServiceContract特性的类也是服务类型。然而,先为接口添加ServiceContract特性,然后用类实现接口的方法,能生成一个可被任意多服务类型实现的服务契约。这样,可根据需要将一个实现了服务契约的服务类型用另外一个替换。

为终结点指定地址和绑定

为终结点指定地址和绑定并不需要编写任何代码,实现上,这一般是管理员而不是程序员的工作。虽然也可以在代码里指定地址和绑定,但如果这样做,为更改地址和绑定就需要修改代码了。WCF的一个重要创新就是将如何开发软件与软件如何通信分开。软件如何通信是由绑定确定的。所以,一般情况下,我们应该避免在代码中指定终结点的地址和绑定,而应该通过配置宿主应用程序来指定。

手动方式指定地址和绑定

为宿主程序添加程序配置文件app.config,该文件内容示例如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<!-- 指定该配置文件所配置的宿主程序承载的服务类型 -->
<service name="DerivativesCalculator.DerivativesCalculatorServiceType">
<host>
<baseAddresses>
<!-- 使用URI格式指定服务宿主的基地址 -->
<add baseAddress="http://localhost:8000/Derivatives/" />
<add baseAddress="net.tcp://localhost:8010/Derivatives/" />
</baseAddresses>
</host>
<!-- 为服务类型功能提供一个终结点,包括地址、绑定、契约 -->
<endpoint address="Calculator" binding="basicHttpBinding" 
contract="DerivativesCalculator.IDerivativesCalculatorServiceType" />
</service>
</services>
</system.serviceModel>
</configuration>

注意:

1. 为服务终结点设定的地址是基地址的相对地址。URI第一个“/”前的部分称为方案(scheme),提供给WCF服务的每个基地址必须使用不同的策略。

2. 终结点的绑定由binding="basicHttpBinding"确定。WCF绑定定义了与服务通信的协议组合。每个协议由一个绑定元素(binding element)表示,而每个绑定都由一组绑定元素组成。WCF的信道层主要提供的就是绑定元素。

一类特定绑定元素实现了传送消息的协议,其中之一便是实现了HTTP的绑定元素,另一个实现了TCP协议。

另外一类特殊的绑定元素定义了消息编码的协议。WCF提供了三个这类绑定元素:一种是将SOAP消息编码成文本;另一种将SOAP消息编码成二进制格式;第三种将SOAP消息根据SOAP而MTOM(Message Transmission Optimization Mechanism,消息传输优化机制)编码。MTOM编码适合那些包含大量二进制数据的SOAP消息。

既不是传输协议绑定元素也不是消息编码绑定元素的例子有实现WS-Security协议和WS-ReliableMessaging协议的绑定元素。WCF中可扩展性很重要的一个方面就是任何软件开发者都可提供新的绑定元素。WCF绑定就是一组绑定元素,它们至少包含一个传输绑定元素及数量不限的其他绑定元素。如果没有指定消息编码绑定元素,那么传输协议绑定元素将采用默认的消息编码协议。

绑定可以在代码或配置文件中通过逐一选择绑定元素来定义,WCF也提供了几个包含常用绑定元素组合的类,这些类被称为预定义绑定。BasicHttpBinding是预定义的绑定之一,它代表了HTTP传输绑定元素与将SOAP消息编码成文本格式的绑定元素的组合。BasicHttpBinding根据WS-I Basic Profile Specification 1.1配置这些绑定元素配置。后者是一组挑选取出来的Web服务规范,其目的是提高各种平台上的Web服务及用户间的互操作性。

全部现有的预定义绑定见下表,它们都直接或间接继承自类System.ServiceModel.Channels.Binding。

在上例中,终结点的地址被设为Calculator,这个地址是基地址的相对地址。那这个终结点的基地址是之前定义的哪一个呢?这是由基地址的策略和传输绑定元素实现的传输协议来决定的。下表列出了它们的对应关系:

部署服务

由于安全因素,默认在IE中访问http基地址显示的页面中,元数据发布功能被禁止了。这样,除非开发者或管理员明确设定了需要显示的内容,其他任何有关服务的信息都不会暴露。要发布元数据,我们可更改配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
......
<service name="DerivativesCalculator.DerivativesCalculatorServiceType"
behaviorConfiguration="DerivativesCalculatorService">
</service>
<behaviors>
<serviceBehaviors>
<behavior name="DerivativesCalculatorService">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
......
</configuration>

上面更改的实质就是让服务在响应HTTP GET的访问时,生成它自己的元数据。

在浏览器中的URI后加上wsdl查询,如http://localhost:8000/Derivatives/?wsdl,这时服务的WSDL就可显示了。

使用服务

我们可使用svcutil工具来生成WCF服务的客户端代码类及相关配置文件,如:

svcutil http://localhost:8000/Derivatives/ /out:Client.cs /config:app.config

该命令在运行WCF的服务元数据工具时,将服务使用的http策略的基地址作为命令参数。如果该地址使用http策略,且该服务已启用了通过HTTP GET发布元数据功能,服务元数据工具便能获取到该服务的WSDL和其他相关元数据。默认情况下,它会创建一个与服务通信的代码类,且生成一个包含服务终结点定义的.NET程序配置文件。其代码类的使用见下例:

public static void Main(string[] args)
{
decimal result = 0;
using(DerivativesCalculatorProxy proxy = new DerivativesCalculatorProxy("BasicHttpBinding_IDerivativesCalculator))
{
proxy.Open();
result = proxy.CalculateDerivative(new string[]{"MSFT"}, new decimal[]{ 3 }, new string[]{} };
proxy.Close();
}
}

添加到Client项目的app.config文件必须有这个终结点的定义,包括地址、绑定和契约:

<client>
<endpoint
address="http://localhost:8000/Derivatives/Calculator"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IDerivativesCalculator"
contract="IDerivativesCalculator"
name="BasicHttpBinding_IDerivativesCalculator" />
</client>

注意,终结点定义中的名称与传给代理类构造函数的参数是一致的。

这个终结点配置中应用的名称为BasicHttpBinding_IDerivativesCalculator的绑定配置实际上给出了预定义的BasicHttpBinding的属性默认值。

我们也可以自己写一个代理类,而不需使用Windows服务元数据工具来生成。这只需定义一个从WCF的ClientBase<T>泛型继承的类,且实现服务的契约即可。

[ServiceContract]
public interfact IDerivativesCalculator
{
[OperationContract]
decimal CalculateDerivative(string[] symbols, decimal[] parameters, string[] functions);
...
}

public partial class DerivativesCalculatorProxy : ClientBase<IDerivativesCalculator>, IDerivativesCalculator
{
public decimal CalculateDerivative(string[] symbols, decimal[] parameters, string[] functions)

{

return base.Channel.CalculateDerivative(symbols, parameters, functions);

}
}

另外一种编写服务客户端的方法是给定一个契约的定义:

IDerivativesCalculator proxy = new ChannelFactory<IDerivativesCalculator>("BasicHttpBinding_IDerivativesCalculator").CreateChannel();
proxy.CalculateDerivative(...);
((IChannel)proxy).Close();

ChannelFactory<T>泛型是在System.ServiceModel.Channels命名空间里定义的。第一个编写客户端的方法产生一个可复用的代理类,而第二个方法只是生成了一个代理变量。第三种方法是使用MetadataExchangeClient类自己下载服务的元数据,然后在执行时根据元数据相应的配置代理。

在IIS中承载WCF服务

只有那些所有终结点都具有HTTP绑定的服务才可承载在IIS 5.1或IIS 6中。IIS 7中添加了一个新功能叫Windows激活服务(Windows Activation Service),它可将使用任何传输协议的消息转发给.NET程序集。这样,不管WCF服务使用何种传输协议都可在IIS 7中承载。

















本文转自cnn23711151CTO博客,原文链接:http://blog.51cto.com/cnn237111/572498 ,如需转载请自行联系原作者



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章