WCF学习之旅——第一个WCF示例(二)
WCF学习之旅目录
第四步:通过自我寄宿的方式寄宿服务
WCF服务需要依存一个运行着的进程(宿主),服务寄宿就是为服务指定一个宿主的过程。WCF是一个基于消息的通信框架,采用基于终结点(Endpoint)的通信手段。
终结点主要由地址(Address)、绑定(Binding)和协定(Contract)三要素组成,如图所示。由于三要素应为首字母分别为ABC,所以就有了易于记忆的公式:Endpoint = ABC。一个终结包含了实现通信所必需的所有信息。如下图。
终结点三要素
- 地址(Address):一个指示可以查找终结点的位置的地址。地址决定了服务的位置,解决了服务寻址的问题
- 绑定(Binding):一个指定客户端如何与终结点进行通信的绑定。绑定实现了通信的所有细节,包括网络传输、消息编码,以及其他为实现某种功能(比如安全、可靠传输、事务等)对消息进行的相应处理。WCF中具有一系列的系统定义绑定,比如BasicHttpBinding、WsHttpBinding、NetTcpBinding等,
- 协定(Contract):一个标识可用操作的协定。协定是对服务操作的抽象,也是对消息交换模式以及消息结构的定义。
- 行为(Behavior):一组指定终结点的本地实现细节的行为。
服务寄宿的目的就是开启一个进程,为WCF服务应用提供一个运行的环境。通过为服务添加一个或多个终结点,使之暴露给潜在的服务调用者。服务调用者最终通过相匹配的终结点对该服务进行调用。
一)代码方式实现寄宿
我们可以通过代码的方式完成所有的服务寄宿工作。在Hosting项目中的Program.cs文件中的Main方法中,通过代码实现对 BookService的WCF服务应用的寄宿实现。具体代码如下:
using SCF.WcfService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
namespace Hosting
{
class Program
{
// 无配置文件的启动程序
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(BookService)))
{
host.AddServiceEndpoint(typeof(IBookService), new WSHttpBinding(),
"http://127.0.0.1:8888/BookService");
if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
{
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
behavior.HttpGetUrl = new Uri("http://127.0.0.1:8888/BookService/metadata");
host.Description.Behaviors.Add(behavior);
}
host.Opened += delegate
{
Console.WriteLine("BookService,按任意键终止服务!");
};
host.Open();
Console.Read();
}
}
}
WCF服务寄宿通过一个特殊的对象完成:ServiceHost。在上面的代码基本实现的功能说明,基于WCF服务应用的类型(typeof(BookService))创建了ServieHost对象,并添加了一个终结点。具体的地址为http://127.0.0.1:8888/BookService,采用了WSHttpBinding,并指定了服务协定的类型IBookService。
松耦合是SOA的一个基本的特征,WCF服务应用中客户端和服务端的松耦合体现在客户端只需要了解WCF服务基本的描述,而无需知道具体的实现细节,就可以实现正常的WCF服务调用。WCF服务的描述通过元数据(Metadata)的形式发布出来。WCF中元数据的发布通过一个特殊的服务行为ServiceMetadataBehavior实现。在上面提供的服务寄宿代码中,我们为创建的ServiceHost添加了ServiceMetadataBehavior,并采用了基于HTTP-GET的元数据获取方式,元数据的发布地址通过ServiceMetadataBehavior的HttpGetUrl指定。在调用ServiceHost的Open方法对服务成功寄宿后,我们可以通过该地址获取服务相关的元数据。
3) 运行已经生成的hosting.exe,然后在浏览器地址栏上键入http://127.0.0.1:8888/BookService/metadata,你将会得到以WSDL形式体现的服务元数据,如下图所示。
通过HTTP-GET的方式获取WCF服务的元数据
二)配置文件方式实现寄宿
在实际应用中,对于WCF应用服务的寄宿,一般不会直接通过编码的方式进行终结点的添加和服务行为的定义,而是通过写配置文件的方式实现,这样可以方便修改。
1) 现在我在Hosting项目中添加一个app.config配置文件,把下面的配置信息添加到配置文件app.config中。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:8888/BookService/metadata" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="metadataBehavior" name="SCF.WcfService.BookService">
<endpoint address="http://127.0.0.1:8888/BookService"
binding="wsHttpBinding" bindingConfiguration="" contract="SCF.WcfService.IBookService" />
</service>
</services>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
2) 增加app.config配置文件与配置信息之后,我们原来写的寄宿代码就不能使用了,需要进行服务寄宿代码的修改,而且代码会变的更简洁,只需几行代码就可以了。代码如下。
static void Main(string[] args)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(BookService)))
{
host.Opened += delegate
{
Console.WriteLine("BookService,使用配置文件,按任意键终止服务!");
};
host.Open();
Console.Read();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
3) 执行hosting.exe应用程序,结果如下图。