WCF揭秘——自定义绑定

来源:互联网 发布:家庭理财软件 编辑:程序博客网 时间:2024/05/17 18:44

一、什么是绑定

绑定是预先配置好的信道栈,它代表了服务器与客户端之间的通信约定,每个绑定都会指定了通信所应用到的传输协调、编码等属性。在Framework3.5中已经包含basicHttpBinding、wsHttpBinding、wsDualHttpBinding、webHttpBinding、netTcpBinding、netNamedPipeBinding、netMsmqBinding、netPeerTcpBinding、msmqIntegrationBinding、wsFedrationHttpBinding、ws2007HttpBinding、ws2007FederationHttpBinding等多种绑定。其中不同的绑定支持不同的传输协议,在消息编码、传输安全、通讯方式、安全模式、可靠性会话、事务流方面有着不同的属性,能够满足大部分信息通讯的要求。

绑定类名称传输编码消息版本安全模式可靠性会话事务流BasicHttpBindingHTTP文本SOAP 1.1不支持不支持WSHttpBindingHTTP文本SOAP 1.2 WS-Addressing 1.0消息禁用WS-AtomicTransactionsWSDualHttpBindingHTTP文本SOAP 1.2 WS-Addressing 1.0消息启用WS-AtomicTransactionsWSFederationHttpBindingHTTP文本SOAP 1.2 WS-Addressing 1.0消息禁用WS-AtomicTransactionsNetTcpBindingTCP二进制SOAP 1.2传输禁用OleTransactionsNetPeerTcpBindingP2P二进制SOAP 1.2传输不支持不支持NetNamedPipesBinding命名管道二进制SOAP 1.2传输不支持OleTransactionsNetMsmqBindingMSMQ二进制SOAP 1.2消息不支持不支持MsmqIntegrationBindingMSMQ不支持不支持传输不支持不支持CustomBinding自定义 自定义 自定义自定义  自定义自定义

 

二、自定义绑定元素

当预定义的绑定无法满足用户需求时,可以使用CustomBinding类开发自定义绑定,该类存在于System.ServiceModel.Channels命名空间。用户可以根据需要绑定以下属性: 事务(TransactionFlowBindingElement类)、可靠性会话(ReliableSessionBindingElement 类)、安全( SecurityBindingElement 类)、流安全、单工双工工作模式、信息编码、传输绑定等,其中信息编码和传输绑定元素是自定义绑定的必要属性,其他属性用户可根据需求制定。

  • 传输绑定元素(必要),用户可选其中一种传输绑定模式。
传输信道传输绑定元素绑定扩展配置元素TCP传输信道TcpTransportBindingElementTcpTransportElement<tcpTransport>HTTP传输信道HttpTransportionBindingElement  HttpTransportElement  <httpTransport>HTTPS传输信道HttpTransportationBindingElementHttpTransportElement<httpTransport>MSMQ传输信道MSMQTransportBindingElementMSMQTransportElement<msmqTransport>MSMQ集成传输信道MSMQIntegrationBindingElement  MSMQIntegrationBindingElement<msmqIntegration>命名管道传输信道NamedPipeTransportBindingElementNamedPipeTransportElement  <namedPipeTransport>P2P传输信道 PeerTransportBindingElementPeerTransportElement<peerTransport>UDP传输信道UdpTransportBindingElementUdpTransportElement<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 : IExampleService12     {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.Client35 {36     class Program37     {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.Client36 {37     class Program38     {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 NetHttpSecurityMode58     {59         Transport,60         TransportCredentialOnly,61         None62     }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             set102             {103                 if (value != null)104                 {105                     value.CopyTo(binaryEncoding.ReaderQuotas);106                 }107             }108         }109 110         public EnvelopeVersion EnvelopeVersion111         {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 Scheme34         {35             get36             {37                 if (securityMode == NetHttpSecurityMode.Transport)38                 {39                     return httpsTransport.Scheme;40                 }41                 else42                 {43                     return httpTransport.Scheme;44                 }45             }46         }47 48         //创建当前绑定元素49         public override BindingElementCollection CreateBindingElements()50         {   // return collection of BindingElements51             BindingElementCollection bindingElements = new BindingElementCollection();52             bindingElements.Add(binaryEncoding);53 54             if (this.securityMode == NetHttpSecurityMode.Transport)55             {56                 bindingElements.Add(this.httpsTransport);57             }58             else59             {60                 if (this.securityMode == NetHttpSecurityMode.TransportCredentialOnly)61                 {62                     this.httpTransport.AuthenticationScheme = AuthenticationSchemes.Negotiate;63                 }64                 else65                 {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                 else12                 {13                     return ProtectionLevel.None;14                 }15             }16         }17 18         System.Net.Security.ProtectionLevel ISecurityCapabilities.SupportedResponseProtectionLevel19         {20             get21             {22                 if (securityMode == NetHttpSecurityMode.Transport)23                 {24                     return ProtectionLevel.EncryptAndSign;25                 }26                 else27                 {28                     return ProtectionLevel.None;29                 }30             }31         }32 33         bool ISecurityCapabilities.SupportsClientAuthentication34         {35             get36             {37                 if (securityMode == NetHttpSecurityMode.None)38                 {39                     return false;40                 }41                 else42                 {43                     return true;44                 }45             }46         }47 48         bool ISecurityCapabilities.SupportsClientWindowsIdentity49         {50             get51             {52                 if (securityMode == NetHttpSecurityMode.None)53                 {54                     return false;55                 }56                 else57                 {58                     return true;59                 }60             }61         }62 63         bool ISecurityCapabilities.SupportsServerAuthentication64         {65             get66             {67                 if (securityMode == NetHttpSecurityMode.None)68                 {69                     return false;70                 }71                 else72                 {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             else13             {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 Service11     {12         //设置服务的基础URI13         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 : IEchoService41     {42         #region IEchoService Members43 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         #endregion55     }56 }
在MSDN中已经有此开发实例,在此也不再作详细解释。致此,已经对自定义绑定作出详细的说明,用户可以分别使用代码、配置文件和绑定扩展类三种方式来开发自定义绑定。在使用复杂的面向服务开发系统中实现自定义绑定,可以按照不同的需求实现服务,绑定不同的传输协调,文本传输方式,限制最大传输流量等,不失为实现分布式开发的一种手段。

相关文章

自定义绑定

简单的WCF开发实例

使用AJAX+WCF进行页面开发

共享数据契约

可靠性会话功能

对JAVA与.NET开发有兴趣的朋友欢迎加入QQ群:162338858 点击这里加入此群

cnblogs博客园:http://www.cnblogs.com/leslies2/
csdn博客:http://blog.csdn.net/leslies2
原创作品,转载时请注明作者及出处