[转]WCF提供了一个框架/平台来构建分布的互联系统,WCF是SOA的,是面向服务的。但一个Service必须至少包含一个Endpoint,否则,试想一下,客户端连到哪里来获得一个Service?一个服务(Service)必须告诉外部在某个Endpoint提供什么和沟通什么。换句话说:“服务就是: 在某个地方、使用某种通讯协议、传输某种数据类型的消息”。
客户只能通过服务的Endpoint来访问服务。每个Endpoint必须包含地址、绑定和协议(契约), host 进程会提供 Endpoint 供客户端调用。一个服务至少包含一个Endpoint,可以有多个Endpoint,多个绑定和多个契约。多个 Endpoint 可以共享相同的绑定和契约,每个服务又可以提供多个 Endpoint 供客户端掉用。每个Endpoint用唯一的地址(Address)来区分于其它的Endpoint,绑定指定了服务与外部通讯的方式( 例如 NetTcp, MSMQ等等),而契约指定了消息格式、Endpoint会发生的行为具体提供什么服务,Service behaviour可以控制服务的运行时特性( 例如 线程问题,service实例管理等)。当服务收到一条消息,服务开始执行。一个服务的描述和实现代码的CLR runtime instance被创建。WCF运行时(WCF Runtime)控制消息的格式化,消息的收发等等。
- Address: WCF提供服务的地址,每个Endpoint的地址是唯一的;Address可以是http://mymachine:8080/myservice,也可以是Net.tcp://localhost:8000/WCFService/tcpmex。Address类型有:Endpoint address / Base address / MEX address。
- Binging: 指定通信协议和安全方式,例如 Http,NetTcp, MSMQ等等。默认提供的9种见下图。
- Contract: 具体这个服务提供什么功能,Client和Server交互的输入输入,消息格式,其它约定等。
- Behaviour: 可以控制服务的运行时特性( 例如 线程问题,service实例管理等)。分两类:service behaviors / operation behaviors。这些行为,或特性,可以通过配置runtime属性配置文件,或自定义行为来实现。
[OperationBehavior] 特性
- AddressFilterMode
- AutomaticSessionShutdown
- ConcurrencyMode
- ConfigurationName
- IgnoreExtensionDataObject
- IncludeExceptionDetailInFaults
- InstanceContextMode
- ReleaseServiceInstanceOnTransactionComplete
- TransactionAutoCompleteOnSessionClose
- TransactionIsolationLevel
- TransactionTimeout
- UseSynchronizedContext
- ValidateMustUnderstand
[OperationBehavior] 特性
- AutoDisposeParameters
- Impersonation
- ReleaseInstanceMode
- TransactionAutoComplete
- TransactionScopeRequired
WCF Contract 三种基本契约类型:
- Service Contract:(WSDL) 定义服务方法,也就是说,对客户端来说,在某个Endpoint什么操作或服务可用.
- Data Contract: (XSD) 定义服务方法的数据类型.
- Message Contract: (SOAP) 在创建消息的时候控制消息头.
例子:
using System;
using System.ServiceModel;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.IO;
namespace WCFService
{
[ServiceContract]
public interface IServiceClass
{
[OperationContract]
ExplicitNumbers Add(ExplicitNumbers en1, ExplicitNumbers en2);
[OperationContract]
ExplicitNumbers Subtract(ExplicitNumbers en1, ExplicitNumbers en2);
}
[DataContract]
public class ExplicitNumbers
{
[DataMember]
public double Explicit1;
[DataMember]
public double Explicit2;
public ExplicitNumbers(double explicit1, double explicit2)
{
this.Explicit1 = explicit1;
this.Explicit2 = explicit2;
}
}
public class ServiceClass : IServiceClass
{
public ExplicitNumbers Add(ExplicitNumbers en1, ExplicitNumbers en2)
{
return new ExplicitNumbers(en1.Explicit1 + en2.Explicit1, en1.Explicit2 + en2.Explicit2);
}
public ExplicitNumbers Subtract(ExplicitNumbers en1, ExplicitNumbers en2)
{
return new ExplicitNumbers(en1.Explicit1 - en2.Explicit1, en1.Explicit2 - en2.Explicit2);
}
}
}
<?xml version=”1.0” encoding=”utf-8” ?>
<configuration>
<system.serviceModel>
<services>
<service name =”WCFService.ServiceClass” behaviorConfiguration=”metadataSupport”>
<host>
<baseAddresses>
<add baseAddress=”http://localhost:8080/WCFService”/>
<add baseAddress=”net.pipe://localhost/WCFService”/>
<add baseAddress=”net.tcp://localhost:8000/WCFService”/>
</baseAddresses>
</host>
<endpoint address=”” binding=”wsHttpBinding” contract=”WCFService.IServiceClass”/>
<endpoint address=”tcpmex” binding=”mexTcpBinding” contract=”IMetadataExchange”/>
<endpoint address=”namedpipemex” binding=”mexNamedPipeBinding” contract=”IMetadataExchange”/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name=”metadataSupport”>
<serviceMetadata httpGetEnabled=”false” httpGetUrl=””/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
WCF默认提供的9种Binding类型:
Endpoint可以通过代码定义:
Uri bpa = new Uri(“net.pipe://localhost/NetNamedPipeBinding”);
Uri tcpa = new Uri(“net.tcp://localhost:8000/TcpBinding”);
sh = new ServiceHost(typeof(ServiceClass), bpa, tcpa);
NetNamedPipeBinding pb = new NetNamedPipeBinding();
NetTcpBinding tcpb = new NetTcpBinding();
ServiceMetadataBehavior mBehave = new ServiceMetadataBehavior();
sh.Description.Behaviors.Add(mBehave);
sh.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexTcpBinding(), “mex”);
sh.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexNamedPipeBinding(), “mex”);
sh.AddServiceEndpoint(typeof(IServiceClass), pb, bpa);
sh.AddServiceEndpoint(typeof(IServiceClass), tcpb, tcpa);
sh.Open();
Endpoint可以通过配置文件定义:
<?xml version=”1.0” encoding=”utf-8” ?>
<configuration>
<system.serviceModel>
<services>
<service name =”WCFService.ServiceClass” behaviorConfiguration=”metadataSupport”>
<host>
<baseAddresses>
<add baseAddress=”net.pipe://localhost/WCFService”/>
<add baseAddress=”net.tcp://localhost:8000/WCFService”/>
<add baseAddress=”http://localhost:8080/WCFService”/>
</baseAddresses>
</host>
<endpoint address=”tcpmex” binding=”mexTcpBinding” contract=”IMetadataExchange”/>
<endpoint address=”namedpipemex” binding=”mexNamedPipeBinding” contract=”IMetadataExchange”/>
<endpoint address=”” binding=”wsHttpBinding” contract=”WCFService.IServiceClass”/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name=”metadataSupport”>
<serviceMetadata httpGetEnabled=”false” httpGetUrl=””/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Endpoint可以通过配置文件定义行为( Behaviour ):
<?xml version=”1.0” encoding=”utf-8” ?>
<configuration>
<system.serviceModel>
<services>
<service name =”WCFService.ServiceClass” behaviorConfiguration=”metadataSupport”>
<host>
<baseAddresses>
<add baseAddress=”net.pipe://localhost/WCFService”/>
<add baseAddress=”net.tcp://localhost:8000/WCFService”/>
<add baseAddress=”http://localhost:8080/WCFService”/>
</baseAddresses>
</host>
<endpoint address=”tcpmex” binding=”mexTcpBinding” contract=”IMetadataExchange”/>
<endpoint address=”namedpipemex” binding=”mexNamedPipeBinding” contract=”IMetadataExchange”/>
<endpoint address=”” binding=”wsDualHttpBinding” contract=”WCFService.IServiceClass”/>
<!--<endpoint address=”mex” binding=”mexHttpBinding” contract=”IMetadataExchange”/>-->
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name=”metadataSupport”>
<serviceDebug includeExceptionDetailInFaults=”true”/>
<serviceMetadata httpGetEnabled=”false” httpGetUrl=””/>
<serviceThrottling maxConcurrentCalls=”10” maxConcurrentInstances=”5” maxConcurrentSessions=”5”/>
<serviceSecurityAudit auditLogLocation=”Application” suppressAuditFailure=”false”/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>