WCF揭秘——自定义绑定

一、什么是绑定

绑定是预先配置好的信道栈,它代表了服务器与客户端之间的通信约定,每个绑定都会指定了通信所应用到的传输协调、编码等属性。在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-AtomicTransactions
WSDualHttpBindingHTTP文本SOAP 1.2 WS-Addressing 1.0消息启用WS-AtomicTransactions
WSFederationHttpBindingHTTP文本SOAP 1.2 WS-Addressing 1.0消息禁用WS-AtomicTransactions
NetTcpBindingTCP二进制SOAP 1.2传输禁用OleTransactions
NetPeerTcpBindingP2P二进制SOAP 1.2传输不支持不支持
NetNamedPipesBinding命名管道二进制SOAP 1.2传输不支持OleTransactions
NetMsmqBindingMSMQ二进制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 : 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 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WCF(Windows Communication Foundation)是一个用于创建分布式应用程序的框架。在WCF中,可以使用多种方式来托管(host)服务,包括IIS、Windows服务、自定义宿主等。 下面介绍一下如何使用自定义宿主来托管WCF服务: 1. 创建一个实现了System.ServiceModel.ServiceHost类的自定义宿主。 ```csharp public class MyServiceHost : ServiceHost { public MyServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) { } protected override void OnOpening() { // 在打开宿主之前可以进行一些预处理工作 base.OnOpening(); } protected override void OnClosed() { // 在关闭宿主之前可以进行一些清理工作 base.OnClosed(); } } ``` 2. 在自定义宿主中添加WCF服务的终结点。 ```csharp public class MyServiceHost : ServiceHost { public MyServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) { } protected override void OnOpening() { // 添加终结点 this.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "http://localhost/MyService"); base.OnOpening(); } protected override void OnClosed() { base.OnClosed(); } } ``` 3. 在应用程序中创建自定义宿主实例,并启动宿主。 ```csharp var host = new MyServiceHost(typeof(MyService)); host.Open(); ``` 4. 关闭自定义宿主。 ```csharp host.Close(); ``` 通过自定义宿主,可以对WCF服务进行更加细粒度的控制和定制,比如添加自定义行为、启用安全性等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值