一、什么是绑定
绑定是预先配置好的信道栈,它代表了服务器与客户端之间的通信约定,每个绑定都会指定了通信所应用到的传输协调、编码等属性。在Framework3.5中已经包含basicHttpBinding、wsHttpBinding、wsDualHttpBinding、webHttpBinding、netTcpBinding、netNamedPipeBinding、netMsmqBinding、netPeerTcpBinding、msmqIntegrationBinding、wsFedrationHttpBinding、ws2007HttpBinding、ws2007FederationHttpBinding等多种绑定。其中不同的绑定支持不同的传输协议,在消息编码、传输安全、通讯方式、安全模式、可靠性会话、事务流方面有着不同的属性,能够满足大部分信息通讯的要求。
绑定类名称 | 传输 | 编码 | 消息版本 | 安全模式 | 可靠性会话 | 事务流 |
BasicHttpBinding | HTTP | 文本 | SOAP 1.1 | 无 | 不支持 | 不支持 |
WSHttpBinding | HTTP | 文本 | SOAP 1.2 WS-Addressing 1.0 | 消息 | 禁用 | WS-AtomicTransactions |
WSDualHttpBinding | HTTP | 文本 | SOAP 1.2 WS-Addressing 1.0 | 消息 | 启用 | WS-AtomicTransactions |
WSFederationHttpBinding | HTTP | 文本 | SOAP 1.2 WS-Addressing 1.0 | 消息 | 禁用 | WS-AtomicTransactions |
NetTcpBinding | TCP | 二进制 | SOAP 1.2 | 传输 | 禁用 | OleTransactions |
NetPeerTcpBinding | P2P | 二进制 | SOAP 1.2 | 传输 | 不支持 | 不支持 |
NetNamedPipesBinding | 命名管道 | 二进制 | SOAP 1.2 | 传输 | 不支持 | OleTransactions |
NetMsmqBinding | MSMQ | 二进制 | SOAP 1.2 | 消息 | 不支持 | 不支持 |
MsmqIntegrationBinding | MSMQ | 不支持 | 不支持 | 传输 | 不支持 | 不支持 |
CustomBinding | 自定义 | 自定义 | 自定义 | 自定义 | 自定义 | 自定义 |
二、自定义绑定元素
当预定义的绑定无法满足用户需求时,可以使用CustomBinding类开发自定义绑定,该类存在于System.ServiceModel.Channels命名空间。用户可以根据需要绑定以下属性: 事务(TransactionFlowBindingElement类)、可靠性会话(ReliableSessionBindingElement 类)、安全( SecurityBindingElement 类)、流安全、单工双工工作模式、信息编码、传输绑定等,其中信息编码和传输绑定元素是自定义绑定的必要属性,其他属性用户可根据需求制定。
- 传输绑定元素(必要),用户可选其中一种传输绑定模式。
传输信道 | 传输绑定元素 | 绑定扩展 | 配置元素 |
TCP传输信道 | TcpTransportBindingElement | TcpTransportElement | <tcpTransport> |
HTTP传输信道 | HttpTransportionBindingElement | HttpTransportElement | <httpTransport> |
HTTPS传输信道 | HttpTransportationBindingElement | HttpTransportElement | <httpTransport> |
MSMQ传输信道 | MSMQTransportBindingElement | MSMQTransportElement | <msmqTransport> |
MSMQ集成传输信道 | MSMQIntegrationBindingElement | MSMQIntegrationBindingElement | <msmqIntegration> |
命名管道传输信道 | NamedPipeTransportBindingElement | NamedPipeTransportElement | <namedPipeTransport> |
P2P传输信道 | PeerTransportBindingElement | PeerTransportElement | <peerTransport> |
UDP传输信道 | UdpTransportBindingElement | UdpTransportElement | <udpTransport> |
- 信息编码(必要),用户可以选择其中一种信息编码形式
1.TextMessageEncodingBindingElement,文本编码
2.BinaryMessageEncodingBindingElement,二进制编码
3.MtomMessageEncodingBindingElement,MOTM编码
- 流安全绑定元素(可选),用户可以选择其中一种安全绑定形式
1.SslStreamSecurityBindingElement,SSL安全模式
2.WindowsStreamSecurityBindingElement,Window安全模式
- 通信传输(可选),用户可以选择单工或双工其中一种模式
1.CompositeDuplexBindingElement,双工传输模式
2.OneWayBindingElement,单工传输模式
CustomBinding相当于一个绑定的容器,用户可以向里面加入想要的绑定元素,定制一组适合使用的绑定方式。用户可以分别使用代码、配置文件和绑定扩展类三种方式来开发自定义绑定,下面为大家一一说明。
三、使用代码定制自定义绑定
下面以一个最基本的自定义绑定为例子,简单说明一下如何使用代码来定制绑定,首先新建一个服务契约
1 namespace CustomBinding.Server
2 {
3 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IExampleService”。
4 [ServiceContract(Namespace="Services")]
5 public interface IExampleService
6 {
7 [OperationContract]
8 string HelloWorld(string name);
9 }
10
11 public class ExampleService : IExampleService
12 {
13 public string HelloWorld(string name)
14 {
15 return "Hello " + name;
16 }
17 }
18 }
在服务器端,首先新建一个CustomBinding自定义绑定对象,加入传输绑定元素HttpTransportBindingElement,然后加入信息编码元素TextMessageEncodingBindingElement(注意,若使用HttpTransportBindingElement传输方式时,可省略信息编码绑定,那么系统将默认使用TextMessageEncodingBindingElement编码方式)。最后开放元数据,把服务行为的httpGetEnabled设置为true。
1 namespace CustomBinding.Server
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 CustomBinding();
8 }
9
10 public static void CustomBinding()
11 {
12 using (ServiceHost host = new ServiceHost(typeof(ExampleService), new Uri("http://localhost:8081/Services")))
13 {
14 //新建一个CustomBinding对象
15 System.ServiceModel.Channels.CustomBinding customBinding = new System.ServiceModel.Channels.CustomBinding();
16 //设置信息编码
17 customBinding.Elements.Add(new TextMessageEncodingBindingElement());
18 //设置传输绑定元素
19 customBinding.Elements.Add(new HttpTransportBindingElement());
20 //绑定服务契约
21 host.AddServiceEndpoint(typeof(IExampleService), customBinding, "CustomService");
22 //开放元数据
23 ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
24 behavior.HttpGetEnabled = true;
25 host.Description.Behaviors.Add(behavior);
26 host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "CustomService/mex");
27 //启动服务
28 host.Open();
29 Console.WriteLine("Service Start!");
30 Console.ReadKey();
31 host.Close();
32 }
33 }
34 }
在客户端添加服务引用,元数据路径“http://localhost:8081/Services/CustomService/mex”,客户端将对应服务生成wsHttpBinding绑定,并使用TextMessageEncodingBindingElement文本编码元素。最后调用服务测试,若测试成功,系统将显示测试结果:“Hello Leslie”。
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <system.serviceModel>
4 <bindings>
5 <!--由于自定义绑定是使用HttpTransportBindingElement绑定元素,所以客户端将自动生成wsHttpBinding设置-->
6 <wsHttpBinding>
7 <!--注意绑定元素将对应使用TextMessageEncodingBindingElement信息编码元素-->
8 <binding name="CustomBinding_IExampleService" closeTimeout="00:01:00"
9 openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
10 bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
11 maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
12 messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
13 allowCookies="false">
14 <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
15 maxBytesPerRead="4096" maxNameTableCharCount="16384" />
16 <reliableSession ordered="true" inactivityTimeout="00:10:00"
17 enabled="false" />
18 <security mode="None">
19 <transport clientCredentialType="Windows" proxyCredentialType="None"
20 realm="" />
21 <message clientCredentialType="Windows" negotiateServiceCredential="true" />
22 </security>
23 </binding>
24 </wsHttpBinding>
25 </bindings>
26 <client>
27 <endpoint address="http://localhost:8081/Services/CustomService"
28 binding="wsHttpBinding" bindingConfiguration="CustomBinding_IExampleService"
29 contract="ExampleService.IExampleService" name="CustomBinding_IExampleService" />
30 </client>
31 </system.serviceModel>
32 </configuration>
33
34 namespace CustomBinding.Client
35 {
36 class Program
37 {
38 static void Main(string[] args)
39 {
40 //新建服务对象,调用服务方法
41 using (ExampleService.ExampleServiceClient example = new ExampleService.ExampleServiceClient())
42 {
43 string data=example.HelloWorld("Leslie");
44 Console.WriteLine(data);
45 Console.ReadKey();
46 }
47 }
48 }
49 }
四、使用配置文件设置自定义绑定
除了使用代码设置自定义绑定以外,您也可以使用配置文件来设置自定义绑定。下面的例子,将介绍一下如何在自定义绑定中设置可靠性会话功能(关于可靠性会话的详细说明,可参考以下文章http://www.cnblogs.com/leslies2/archive/2011/08/08/2129422.html)。下面依然以上面的例子作为参考,首先在服务器端加入配置文件app.config。加入服务CustomBinding.Server.ExampleService, 绑定服务行为defaultBehavior,在服务行为中打开httpGetEnabled功能。然后把服务地址设置为http://lcoalhost:8082/CustomBinding.Server/ExampleService,加入自定义绑定CustomBinding,绑定契约CustomBinding.Server.IExampleService。最后设置自定义绑定的属性,把可靠性会话时间设置为30分钟,把信息传送方式设置为textMessageEncoding文本方式,把传输通道设置为httpTransport方式。
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <system.serviceModel>
4 <services>
5 <!--根据服务契约类的命名空间设置name名称,设置服务行为defaultBehavior-->
6 <service name="CustomBinding.Server.ExampleService" behaviorConfiguration="defaultBehavior">
7 <host>
8 <baseAddresses>
9 <!--绑定服务地址-->
10 <add baseAddress="http://localhost:8082/CustomBinding.Server/ExampleService"/>
11 </baseAddresses>
12 </host>
13 <!--加入自定义绑定-->
14 <endpoint address="" contract="CustomBinding.Server.IExampleService" binding="customBinding"
15 bindingConfiguration="customBinding"/>
16 <!--开放元数据-->
17 <endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/>
18 </service>
19 </services>
20 <behaviors>
21 <serviceBehaviors>
22 <!--设置服务行为defaultBehavior,把httpGetEnabled设置为true-->
23 <behavior name="defaultBehavior">
24 <serviceMetadata httpGetEnabled="true"/>
25 </behavior>
26 </serviceBehaviors>
27 </behaviors>
28 <bindings>
29 <customBinding>
30 <!--设置自定义绑定的属性,把信息编码方式设置为textMessageEncoding文本形式,并把传输通道设置为httpTransport-->
31 <!--把可靠性会话时间设置为30分钟-->
32 <binding name="customBinding">
33 <reliableSession inactivityTimeout="00:30:00"/>
34 <textMessageEncoding/>
35 <httpTransport/>
36 </binding>
37 </customBinding>
38 </bindings>
39 </system.serviceModel>
40 </configuration>
设置好config文件后,启动服务
1 namespace CustomBinding.Server
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 CustomBinding();
8 }
9
10 public static void CustomBinding()
11 {
12 using(ServiceHost host=new ServiceHost(typeof(ExampleService)))
13 {
14 Console.WriteLine("Service Start!");
15 host.Open();
16 Console.ReadKey();
17 host.Close();
18 }
19 }
20 }
21 }
在客户端添加服务引用,元数据路径“http://lcoalhost:8082/CustomBinding.Server/ExampleService/mex”,客户端将对应服务生成wsHttpBinding绑定,并使用TextMessageEncoding文本编码,值得注意的是客户将对应服务器端生成30分钟可靠性会话。
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <system.serviceModel>
4 <bindings>
5 <!--由于自定义绑定是使用HttpTransportBindingElement绑定元素,所以客户端将自动生成wsHttpBinding设置-->
6 <wsHttpBinding>
7 <!--注意绑定元素将对应使用TextMessageEncodingBindingElement信息编码元素-->
8 <binding name="CustomBinding_IExampleService" closeTimeout="00:01:00"
9 openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
10 bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
11 maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
12 messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
13 allowCookies="false">
14 <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
15 maxBytesPerRead="4096" maxNameTableCharCount="16384" />
16 <!--注意客户端将对应服务器端生成30分钟的可靠性会话-->
17 <reliableSession ordered="true" inactivityTimeout="00:30:00"
18 enabled="true" />
19 <security mode="None">
20 <transport clientCredentialType="Windows" proxyCredentialType="None"
21 realm="" />
22 <message clientCredentialType="Windows" negotiateServiceCredential="true" />
23 </security>
24 </binding>
25 </wsHttpBinding>
26 </bindings>
27 <client>
28 <endpoint address="http://localhost:8082/CustomBinding.Server/ExampleService"
29 binding="wsHttpBinding" bindingConfiguration="CustomBinding_IExampleService"
30 contract="ExampleService.IExampleService" name="CustomBinding_IExampleService" />
31 </client>
32 </system.serviceModel>
33 </configuration>
34
35 namespace CustomBinding.Client
36 {
37 class Program
38 {
39 static void Main(string[] args)
40 {
41 //新建服务对象,调用服务方法
42 using (ExampleService.ExampleServiceClient example = new ExampleService.ExampleServiceClient())
43 {
44 string data=example.HelloWorld("Leslie");
45 Console.WriteLine(data);
46 Console.ReadKey();
47 }
48 }
49 }
50 }
五、使用绑定扩展类实现自定义绑定
使用扩展类实现自定义绑定是最灵活,使用最广泛的一种自定义绑定方式,特别适用在大型的分布式系统开发中使用,它可以根据需要实现不同的绑定类型,以适应在各种不同平台上使用。对比起前面两种方法,它的实现方式稍微复杂一些,下而为大家简单介绍一下。在MSDN上有绑定扩展类的开发实例,源代码下载 http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=21459。打开项目\WF_WCF_Samples\WCF\Extensibility\Binding\NetHttpBinding,
下面以此为项目例子详细讲述一下绑定扩展类的实现方式。
其中NetHttpBindingElement继承了StandardBindingElement,它暴露了配置文件中自定义绑定的可配置属性,NetHttpConfigurationStrings中设置了可配置元素的名称,NetHttpDefaults中设置了配置元素的默认值,NetHttpBindingCollectionElements提供配置节的基类,并继承了StandardBindingCollectionElement<NetHttpBinding, NetHttpBindingElement>,可以为NetHttpBindingElement中列举的属性提供预定义绑定。
1 namespace Microsoft.Samples.NetHttpBinding {
2
3 //提供配置节的基类,为NetHttpBindingElement中列举的属性提供预定义绑定
4 public class NetHttpBindingCollectionElement : StandardBindingCollectionElement<NetHttpBinding, NetHttpBindingElement>
5 {
6 }
7
8 //列举配置属性的名称
9 internal class NetHttpConfigurationStrings {
10
11 internal const string BypassProxyOnLocal = "bypassProxyOnLocal";
12
13 internal const string HostNameComparisonMode = "hostNameComparisonMode";
14
15 internal const string MaxBufferSize = "maxBufferSize";
16
17 internal const string MaxBufferPoolSize = "maxBufferPoolSize";
18
19 internal const string MaxReceivedMessageSize = "maxReceivedMessageSize";
20
21 internal const string ProxyAddress = "proxyAddress";
22
23 internal const string SecurityMode = "securityMode";
24
25 internal const string TransferMode = "transferMode";
26
27 internal const string UseDefaultWebProxy = "useDefaultWebProxy";
28
29 internal const string ReaderQuotas = "readerQuotas";
30 }
31
32 //设置属性的默认值
33 internal class NetHttpDefaults {
34
35 internal const Boolean DefaultBypassProxyOnLocal = true;
36
37 internal const HostNameComparisonMode DefaultHostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
38
39 internal const Int32 DefaultMaxBufferSize = 65536;
40
41 internal const Int64 DefaultMaxBufferPoolSize = 512 * 1024;
42
43 internal const Int64 DefaultMaxReceivedMessageSize = 65536;
44
45 internal const Uri DefaultProxyAddress = null;
46
47 internal const NetHttpSecurityMode DefaultSecurityMode = NetHttpSecurityMode.Transport;
48
49 internal const TransferMode DefaultTransferMode = TransferMode.Buffered;
50
51 internal const Boolean DefaultUseDefaultWebProxy = true;
52
53 internal const XmlDictionaryReaderQuotas DefaultReaderQuotas = null;
54 }
55
56 //列举安全模式
57 public enum NetHttpSecurityMode
58 {
59 Transport,
60 TransportCredentialOnly,
61 None
62 }
63 }
注意若需要在通过*.config文件配置的属性,都必须在NetHttpBindingElement类中一一列举。NetHttpBindingElement必须实现InitializeFrom和OnApplyConfiguration方法,InitializeFrom方法是使用默认值初始化绑定配置元素,而OnApplyConfiguration是在绑定配置文件时调用的方法,必须实现此方法才能使配置文件的绑定属性生效。
1 namespace Microsoft.Samples.NetHttpBinding {
2
3 public class NetHttpBindingElement : StandardBindingElement {
4
5 public NetHttpBindingElement(string configurationName) :
6 base(configurationName) {
7 }
8
9 public NetHttpBindingElement()
10 :
11 this(null) {
12 }
13
14 protected override Type BindingElementType {
15 get {
16 return typeof(NetHttpBinding);
17 }
18 }
19
20 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
[ConfigurationProperty(NetHttpConfigurationStrings.BypassProxyOnLocal, DefaultValue = NetHttpDefaults.DefaultBypassProxyOnLocal)]
21 public bool BypassProxyOnLocal {
22 get {
23 return ((bool)(base[NetHttpConfigurationStrings.BypassProxyOnLocal]));
24 }
25 set {
26 base[NetHttpConfigurationStrings.BypassProxyOnLocal] = value;
27 }
28 }
29
30 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
[ConfigurationProperty(NetHttpConfigurationStrings.HostNameComparisonMode, DefaultValue = NetHttpDefaults.DefaultHostNameComparisonMode)]
31 public System.ServiceModel.HostNameComparisonMode HostNameComparisonMode {
32 get {
33 return ((System.ServiceModel.HostNameComparisonMode)(base[NetHttpConfigurationStrings.HostNameComparisonMode]));
34 }
35 set {
36 base[NetHttpConfigurationStrings.HostNameComparisonMode] = value;
37 }
38 }
39
40 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
[ConfigurationProperty(NetHttpConfigurationStrings.MaxBufferSize, DefaultValue = NetHttpDefaults.DefaultMaxBufferSize)]
41 public int MaxBufferSize {
42 get {
43 return ((int)(base[NetHttpConfigurationStrings.MaxBufferSize]));
44 }
45 set {
46 base[NetHttpConfigurationStrings.MaxBufferSize] = value;
47 }
48 }
49
50 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
[ConfigurationProperty(NetHttpConfigurationStrings.MaxBufferPoolSize, DefaultValue = NetHttpDefaults.DefaultMaxBufferPoolSize)]
51 public long MaxBufferPoolSize {
52 get {
53 return ((long)(base[NetHttpConfigurationStrings.MaxBufferPoolSize]));
54 }
55 set {
56 base[NetHttpConfigurationStrings.MaxBufferPoolSize] = value;
57 }
58 }
59
60 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
[ConfigurationProperty(NetHttpConfigurationStrings.MaxReceivedMessageSize, DefaultValue = NetHttpDefaults.DefaultMaxReceivedMessageSize)]
61 public long MaxReceivedMessageSize {
62 get {
63 return ((long)(base[NetHttpConfigurationStrings.MaxReceivedMessageSize]));
64 }
65 set {
66 base[NetHttpConfigurationStrings.MaxReceivedMessageSize] = value;
67 }
68 }
69
70 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
[ConfigurationProperty(NetHttpConfigurationStrings.ProxyAddress, DefaultValue = NetHttpDefaults.DefaultProxyAddress)]
71 public System.Uri ProxyAddress {
72 get {
73 return ((System.Uri)(base[NetHttpConfigurationStrings.ProxyAddress]));
74 }
75 set {
76 base[NetHttpConfigurationStrings.ProxyAddress] = value;
77 }
78 }
79
80 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
81 [ConfigurationProperty(NetHttpConfigurationStrings.SecurityMode, DefaultValue = NetHttpDefaults.DefaultSecurityMode)]
82 public Microsoft.Samples.NetHttpBinding.NetHttpSecurityMode SecurityMode {
83 get {
84 return ((Microsoft.Samples.NetHttpBinding.NetHttpSecurityMode)(base[NetHttpConfigurationStrings.SecurityMode]));
85 }
86 set {
87 base[NetHttpConfigurationStrings.SecurityMode] = value;
88 }
89 }
90
91 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
92 [ConfigurationProperty(NetHttpConfigurationStrings.TransferMode, DefaultValue = NetHttpDefaults.DefaultTransferMode)]
93 public System.ServiceModel.TransferMode TransferMode {
94 get {
95 return ((System.ServiceModel.TransferMode)(base[NetHttpConfigurationStrings.TransferMode]));
96 }
97 set {
98 base[NetHttpConfigurationStrings.TransferMode] = value;
99 }
100 }
101
102 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
[ConfigurationProperty(NetHttpConfigurationStrings.UseDefaultWebProxy, DefaultValue = NetHttpDefaults.DefaultUseDefaultWebProxy)]
103 public bool UseDefaultWebProxy {
104 get {
105 return ((bool)(base[NetHttpConfigurationStrings.UseDefaultWebProxy]));
106 }
107 set {
108 base[NetHttpConfigurationStrings.UseDefaultWebProxy] = value;
109 }
110 }
111
112 //利用NetHttpConfigurationStrings类设置绑定文件属性名称,利用DefaultValue类设置默认值
[ConfigurationProperty(NetHttpConfigurationStrings.ReaderQuotas, DefaultValue = NetHttpDefaults.DefaultReaderQuotas)]
113 public System.Xml.XmlDictionaryReaderQuotas ReaderQuotas {
114 get {
115 return ((System.Xml.XmlDictionaryReaderQuotas)(base[NetHttpConfigurationStrings.ReaderQuotas]));
116 }
117 set {
118 base[NetHttpConfigurationStrings.ReaderQuotas] = value;
119 }
120 }
121
122 //设置绑定属性
123 protected override ConfigurationPropertyCollection Properties {
124 get {
125 ConfigurationPropertyCollection properties = base.Properties;
126 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.BypassProxyOnLocal, typeof(bool), NetHttpDefaults.DefaultBypassProxyOnLocal));
127 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.HostNameComparisonMode, typeof(System.ServiceModel.HostNameComparisonMode), NetHttpDefaults.DefaultHostNameComparisonMode));
128 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.MaxBufferSize, typeof(int), NetHttpDefaults.DefaultMaxBufferSize));
129 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.MaxBufferPoolSize, typeof(long), NetHttpDefaults.DefaultMaxBufferPoolSize));
130 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.MaxReceivedMessageSize, typeof(long), NetHttpDefaults.DefaultMaxReceivedMessageSize));
131 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.ProxyAddress, typeof(System.Uri), NetHttpDefaults.DefaultProxyAddress));
132 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.SecurityMode, typeof(Microsoft.Samples.NetHttpBinding.NetHttpSecurityMode), NetHttpDefaults.DefaultSecurityMode));
133 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.TransferMode, typeof(System.ServiceModel.TransferMode), NetHttpDefaults.DefaultTransferMode));
134 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.UseDefaultWebProxy, typeof(bool), NetHttpDefaults.DefaultUseDefaultWebProxy));
135 properties.Add(new ConfigurationProperty(NetHttpConfigurationStrings.ReaderQuotas, typeof(System.Xml.XmlDictionaryReaderQuotas), NetHttpDefaults.DefaultReaderQuotas));
136 return properties;
137 }
138 }
139
140 //设置默认值
141 protected override void InitializeFrom(Binding binding) {
142 base.InitializeFrom(binding);
143 NetHttpBinding netHttpBinding = ((NetHttpBinding)(binding));
144 this.BypassProxyOnLocal = netHttpBinding.BypassProxyOnLocal;
145 this.HostNameComparisonMode = netHttpBinding.HostNameComparisonMode;
146 this.MaxBufferSize = netHttpBinding.MaxBufferSize;
147 this.MaxBufferPoolSize = netHttpBinding.MaxBufferPoolSize;
148 this.MaxReceivedMessageSize = netHttpBinding.MaxReceivedMessageSize;
149 this.ProxyAddress = netHttpBinding.ProxyAddress;
150 this.SecurityMode = netHttpBinding.SecurityMode;
151 this.TransferMode = netHttpBinding.TransferMode;
152 this.UseDefaultWebProxy = netHttpBinding.UseDefaultWebProxy;
153 this.ReaderQuotas = netHttpBinding.ReaderQuotas;
154 }
155
156 //在绑定配置文件时发生
157 protected override void OnApplyConfiguration(Binding binding) {
158 if ((binding == null)) {
159 throw new System.ArgumentNullException("binding");
160 }
161 if ((binding.GetType() != typeof(NetHttpBinding))) {
162 throw new System.ArgumentException(string.Format(CultureInfo.CurrentCulture, "Invalid type for binding. Expected type: {0}. Type passed in: {1}.", typeof(NetHttpBinding).AssemblyQualifiedName, binding.GetType().AssemblyQualifiedName));
163 }
164 NetHttpBinding netHttpBinding = ((NetHttpBinding)(binding));
165 netHttpBinding.BypassProxyOnLocal = this.BypassProxyOnLocal;
166 netHttpBinding.HostNameComparisonMode = this.HostNameComparisonMode;
167 netHttpBinding.MaxBufferSize = this.MaxBufferSize;
168 netHttpBinding.MaxBufferPoolSize = this.MaxBufferPoolSize;
169 netHttpBinding.MaxReceivedMessageSize = this.MaxReceivedMessageSize;
170 netHttpBinding.ProxyAddress = this.ProxyAddress;
171 netHttpBinding.SecurityMode = this.SecurityMode;
172 netHttpBinding.TransferMode = this.TransferMode;
173 netHttpBinding.UseDefaultWebProxy = this.UseDefaultWebProxy;
174 netHttpBinding.ReaderQuotas = this.ReaderQuotas;
175 }
176 }
177 }
NetHttpBinding类是实现绑定扩展的核心,首先它实现了NetHttpBindingElement类中所包含BypassProxyOnLocal、HostNameComparisonMode、MaxBufferSize、MaxBufferPoolSize.......等等属性,这使得系统可以通过NetHttpBinding类设置绑定属性。
1 public class NetHttpBinding: : Binding, ISecurityCapabilities
2 {
3 public bool BypassProxyOnLocal
4 {
5 get { return httpTransport.BypassProxyOnLocal; }
6 set
7 {
8 httpTransport.BypassProxyOnLocal = value;
9 httpsTransport.BypassProxyOnLocal = value;
10 }
11 }
12
13 public HostNameComparisonMode HostNameComparisonMode
14 {
15 get { return httpTransport.HostNameComparisonMode; }
16 set
17 {
18 httpTransport.HostNameComparisonMode = value;
19 httpsTransport.HostNameComparisonMode = value;
20 }
21 }
22
23 public int MaxBufferSize
24 {
25 get { return httpTransport.MaxBufferSize; }
26 set
27 {
28 httpTransport.MaxBufferSize = value;
29 httpsTransport.MaxBufferSize = value;
30 }
31 }
32
33 public long MaxBufferPoolSize
34 {
35 get { return httpTransport.MaxBufferPoolSize; }
36 set
37 {
38 httpTransport.MaxBufferPoolSize = value;
39 httpsTransport.MaxBufferPoolSize = value;
40 }
41 }
42
43 public long MaxReceivedMessageSize
44 {
45 get { return httpTransport.MaxReceivedMessageSize; }
46 set
47 {
48 httpTransport.MaxReceivedMessageSize = value;
49 httpsTransport.MaxReceivedMessageSize = value;
50 }
51 }
52
53 public Uri ProxyAddress
54 {
55 get { return httpTransport.ProxyAddress; }
56 set
57 {
58 httpTransport.ProxyAddress = value;
59 httpsTransport.ProxyAddress = value;
60 }
61 }
62
63 public NetHttpSecurityMode SecurityMode
64 {
65 get { return this.securityMode; }
66 set
67 {
68 if (value != NetHttpSecurityMode.Transport &&
69 value != NetHttpSecurityMode.TransportCredentialOnly &&
70 value != NetHttpSecurityMode.None)
71 {
72 throw new ArgumentOutOfRangeException("value");
73 }
74 this.securityMode = value;
75 }
76 }
77
78 public TransferMode TransferMode
79 {
80 get { return httpTransport.TransferMode; }
81 set
82 {
83 httpTransport.TransferMode = value;
84 httpsTransport.TransferMode = value;
85 }
86 }
87
88 public bool UseDefaultWebProxy
89 {
90 get { return httpTransport.UseDefaultWebProxy; }
91 set
92 {
93 httpTransport.UseDefaultWebProxy = value;
94 httpsTransport.UseDefaultWebProxy = value;
95 }
96 }
97
98 public XmlDictionaryReaderQuotas ReaderQuotas
99 {
100 get { return binaryEncoding.ReaderQuotas; }
101 set
102 {
103 if (value != null)
104 {
105 value.CopyTo(binaryEncoding.ReaderQuotas);
106 }
107 }
108 }
109
110 public EnvelopeVersion EnvelopeVersion
111 {
112 get { return EnvelopeVersion.Soap12; }
113 }
........................
........................
114 }
其次,它继承了Binding类,Binding类中包含的CloseTimeout、MessageVersion、OpenTimeout、ReceiveTimeout.......等等属性都可以通过NetHttpBinding设置。值得注意的是,Binding类的Scheme属性必需在NetHttpBinding中实现,此属性是用于绑定通道中所使用到的传输的。而CreateBindingElements方法则是用于创建当前的绑定元素。
1 public class NetHttpBinding : Binding, ISecurityCapabilities
2 {
3 HttpTransportBindingElement httpTransport;
4 HttpsTransportBindingElement httpsTransport;
5 BinaryMessageEncodingBindingElement binaryEncoding;
6
7 NetHttpSecurityMode securityMode;
8
9 public NetHttpBinding() : this(NetHttpSecurityMode.Transport)
10 {
11 }
12 public NetHttpBinding(string configurationName) : this()
13 {
14 ApplyConfiguration(configurationName);
15 }
16
17 public NetHttpBinding(NetHttpSecurityMode securityMode)
18 {
19 if (securityMode != NetHttpSecurityMode.Transport &&
20 securityMode != NetHttpSecurityMode.TransportCredentialOnly &&
21 securityMode != NetHttpSecurityMode.None)
22 {
23 throw new ArgumentOutOfRangeException("securityMode");
24 }
25
26 this.securityMode = securityMode;
27 this.httpTransport = new HttpTransportBindingElement();
28 this.httpsTransport = new HttpsTransportBindingElement();
29 this.binaryEncoding = new BinaryMessageEncodingBindingElement();
30 }
31
32 //绑定通道中所用到的传输
33 public override string Scheme
34 {
35 get
36 {
37 if (securityMode == NetHttpSecurityMode.Transport)
38 {
39 return httpsTransport.Scheme;
40 }
41 else
42 {
43 return httpTransport.Scheme;
44 }
45 }
46 }
47
48 //创建当前绑定元素
49 public override BindingElementCollection CreateBindingElements()
50 { // return collection of BindingElements
51 BindingElementCollection bindingElements = new BindingElementCollection();
52 bindingElements.Add(binaryEncoding);
53
54 if (this.securityMode == NetHttpSecurityMode.Transport)
55 {
56 bindingElements.Add(this.httpsTransport);
57 }
58 else
59 {
60 if (this.securityMode == NetHttpSecurityMode.TransportCredentialOnly)
61 {
62 this.httpTransport.AuthenticationScheme = AuthenticationSchemes.Negotiate;
63 }
64 else
65 {
66 this.httpTransport.AuthenticationScheme = AuthenticationSchemes.Anonymous;
67 }
68 bindingElements.Add(this.httpTransport);
69 }
70
71 return bindingElements.Clone();
72 }
73 ...............
74 ...............
75 }
再次,NetHttpBinding实现了ISecurityCapabilityies接口,此接口是用于设置安全功能协议的。它包含以下几个属性,这些属性都将在NetHttpBinding中实现。
属性 | 说明 |
---|---|
SupportedRequestProtectionLevel | 获取绑定支持的保护级别请求。 |
SupportedResponseProtectionLevel | 获取绑定支持的保护级别响应。 |
SupportsClientAuthentication | 获取一个值,该值指示绑定是否支持客户端身份验证。 |
SupportsClientWindowsIdentity | 获取一个值,该值指示绑定是否支持客户端 Windows 标识。 |
SupportsServerAuthentication | 获取一个值,该值指示绑定是否支持服务器身份验证。 |
1 public class NetHttpBinding : Binding, ISecurityCapabilities
2 {
3 System.Net.Security.ProtectionLevel ISecurityCapabilities.SupportedRequestProtectionLevel
4 {
5 get
6 {
7 if (securityMode == NetHttpSecurityMode.Transport)
8 {
9 return ProtectionLevel.EncryptAndSign;
10 }
11 else
12 {
13 return ProtectionLevel.None;
14 }
15 }
16 }
17
18 System.Net.Security.ProtectionLevel ISecurityCapabilities.SupportedResponseProtectionLevel
19 {
20 get
21 {
22 if (securityMode == NetHttpSecurityMode.Transport)
23 {
24 return ProtectionLevel.EncryptAndSign;
25 }
26 else
27 {
28 return ProtectionLevel.None;
29 }
30 }
31 }
32
33 bool ISecurityCapabilities.SupportsClientAuthentication
34 {
35 get
36 {
37 if (securityMode == NetHttpSecurityMode.None)
38 {
39 return false;
40 }
41 else
42 {
43 return true;
44 }
45 }
46 }
47
48 bool ISecurityCapabilities.SupportsClientWindowsIdentity
49 {
50 get
51 {
52 if (securityMode == NetHttpSecurityMode.None)
53 {
54 return false;
55 }
56 else
57 {
58 return true;
59 }
60 }
61 }
62
63 bool ISecurityCapabilities.SupportsServerAuthentication
64 {
65 get
66 {
67 if (securityMode == NetHttpSecurityMode.None)
68 {
69 return false;
70 }
71 else
72 {
73 return true;
74 }
75 }
76 }
...................
77 }
最后,NetHttpBinding实现 ApplyConfiguration 方法,使系统可以使用配置文件*.config来设置NetHttpBinding的属性。
1 public class NetHttpBinding : Binding, ISecurityCapabilities
2 {
3 private void ApplyConfiguration(string configurationName)
4 {
5 BindingsSection bindings = ((BindingsSection)(ConfigurationManager.GetSection("system.serviceModel/bindings")));
6 NetHttpBindingCollectionElement section = (NetHttpBindingCollectionElement)bindings["netHttpBinding"];
7 NetHttpBindingElement element = section.Bindings[configurationName];
8 if ((element == null))
9 {
10 throw new System.Configuration.ConfigurationErrorsException(string.Format(CultureInfo.CurrentCulture, "There is no binding named {0} at {1}.", configurationName, section.BindingName));
11 }
12 else
13 {
14 element.ApplyConfiguration(this);
15 }
16 }
.....................
17 }
当完成自定义绑定后,可以开始尝试在服务器端启动服务
1 namespace Microsoft.Samples.NetHttpBinding
2 {
3 [ServiceContract]
4 public interface IEchoService
5 {
6 [OperationContract]
7 string Echo(string message);
8 }
9
10 class Service
11 {
12 //设置服务的基础URI
13 static readonly UriBuilder uriBuilder = new UriBuilder("http://" + Environment.MachineName + ":8000/TestService");
14 static void Main(string[] args)
15 {
16 //创建自定义绑定对象
17 NetHttpBinding httpsBinding = new NetHttpBinding();
18 //设置绑定对象的安全模式
19 NetHttpBinding httpBinding = new NetHttpBinding(NetHttpSecurityMode.TransportCredentialOnly);
20 //加入服务对象 ,绑定服务地址
21 ServiceHost serviceHost = new ServiceHost(typeof(EchoService), GetBaseAddress("http", 8000), GetBaseAddress("https", 8443));
22 serviceHost.AddServiceEndpoint(typeof(IEchoService), httpBinding, "BinaryEncoderOverHTTP");
23 serviceHost.AddServiceEndpoint(typeof(IEchoService), httpsBinding, "BinaryEncoderOverHTTPS");
24 serviceHost.Open();
25
26 Console.WriteLine("Service started at: " + serviceHost.ChannelDispatchers[0].Listener.Uri.AbsoluteUri);
27 Console.WriteLine("Service started at: " + serviceHost.ChannelDispatchers[1].Listener.Uri.AbsoluteUri);
28 Console.WriteLine("Press enter to exit...");
29 Console.ReadLine();
30 }
31 static Uri GetBaseAddress(string scheme, int port)
32 {
33 uriBuilder.Scheme = scheme;
34 uriBuilder.Port = port;
35 return uriBuilder.Uri;
36 }
37 }
38
39 //实现服务契约
40 class EchoService : IEchoService
41 {
42 #region IEchoService Members
43
44 public string Echo(string message)
45 {
46 Console.WriteLine("Echo called with: " + message);
47
48 Console.WriteLine("The client is hitting endpoint: {0}", OperationContext.Current.IncomingMessageProperties.Via.AbsoluteUri);
49 ServiceSecurityContext securityContext = OperationContext.Current.ServiceSecurityContext;
50 Console.WriteLine("The client is: {0}", securityContext.IsAnonymous ? "anonymous" : securityContext.PrimaryIdentity.Name);
51 return message;
52 }
53
54 #endregion
55 }
56 }
在MSDN中已经有此开发实例,在此也不再作详细解释。致此,已经对自定义绑定作出详细的说明,用户可以分别使用代码、配置文件和绑定扩展类三种方式来开发自定义绑定。在使用复杂的面向服务开发系统中实现自定义绑定,可以按照不同的需求实现服务,绑定不同的传输协调,文本传输方式,限制最大传输流量等,不失为实现分布式开发的一种手段。
相关文章
对JAVA与.NET开发有兴趣的朋友欢迎加入QQ群:162338858