这部分的前期理论知识比较多,所以我们先从Demo入手,然后再来看理论东西。我们这部分只关注WCF关于邦定的技术,对于其他涉及到的技术不做探讨,由于Binding这部分东西要和其他很多相关技术共同使用,而且涉及到很多WCF中的高级操作,在其他的文章中会逐步提到,这里我们只关心邦定就可以了。
Demo1:二进制邦定通过http
IHelloIndigoService 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Runtime.Serialization;
using
System.ServiceModel;
using
System.Text;
namespace
WcfServiceLibrary2
{
[ServiceContract(Namespace
=
"
http://cnblogs.com/charlesliu
"
)]
public
interface
IHelloIndigoService
{
[OperationContract]
string
HelloIndigo(
string
inputString);
}
}
HelloIndigoService 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Runtime.Serialization;
using
System.ServiceModel;
using
System.Text;
namespace
WcfServiceLibrary2
{
public
class
HelloIndigoService : IHelloIndigoService
{
public
string
HelloIndigo(
string
inputString)
{
return
inputString;
}
}
}
App.config 代码
<?
xml version="1.0" encoding="utf-8"
?>
<
configuration
>
<
system.web
>
<
compilation
debug
="true"
/>
</
system.web
>
<!--
When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries.
-->
<
system.serviceModel
>
<
client
/>
<
services
>
<
service
behaviorConfiguration
="WcfServiceLibrary2.Service1Behavior"
name
="WcfServiceLibrary2.HelloIndigoService"
>
<
endpoint
address
=""
binding
="customBinding"
contract
="WcfServiceLibrary2.IHelloIndigoService"
bindingConfiguration
="binaryOverHttp"
>
<
identity
>
<
dns
value
="localhost"
/>
</
identity
>
</
endpoint
>
<
endpoint
address
="mex"
binding
="mexHttpBinding"
contract
="IMetadataExchange"
/>
<
host
>
<
baseAddresses
>
<
add
baseAddress
="http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary2/Service1/"
/>
</
baseAddresses
>
</
host
>
</
service
>
</
services
>
<
bindings
>
<
customBinding
>
<
binding
name
="binaryOverHttp"
>
<
transactionFlow
transactionProtocol
="WSAtomicTransactionOctober2004"
/>
<
reliableSession
ordered
="true"
/>
<
binaryMessageEncoding
/>
<
httpTransport
/>
</
binding
>
</
customBinding
>
</
bindings
>
<
behaviors
>
<
serviceBehaviors
>
<
behavior
name
="WcfServiceLibrary2.Service1Behavior"
>
<!--
To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment
-->
<
serviceMetadata
httpGetEnabled
="True"
/>
<!--
To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information
-->
<
serviceDebug
includeExceptionDetailInFaults
="False"
/>
</
behavior
>
</
serviceBehaviors
>
</
behaviors
>
</
system.serviceModel
>
</
configuration
>
上面这个Demo和以前的Demo的代码没有什么区别,唯一的不同是在config文件里,加亮的位置体现出了自定义邦定的方法。
Demo2:(Stream流的binding)
IMediaManagerService代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Runtime.Serialization;
using
System.ServiceModel;
using
System.Text;
namespace
WcfServiceLibrary3
{
[ServiceContract]
public
interface
IMediaManagerService
{
[OperationContract]
string
[] GetMediaList();
}
}
IMediaStreaming代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Runtime.Serialization;
using
System.ServiceModel;
using
System.Text;
using
System.IO;
namespace
WcfServiceLibrary3
{
[ServiceContract]
public
interface
IMediaStreaming
{
[OperationContract]
Stream GetMediaStream(
string
media);
}
}
MediaMangerService 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Runtime.Serialization;
using
System.ServiceModel;
using
System.Text;
using
System.IO;
namespace
WcfServiceLibrary3
{
public
class
MediaMangerService : IMediaStreaming, IMediaManagerService
{
public
string
[] GetMediaList()
{
string
[] mediaList
=
new
string
[
1
];
mediaList[
0
]
=
"
WebCast20071101_Video.wmv
"
;
return
mediaList;
}
public
Stream GetMediaStream(
string
media)
{
string
mediaFile
=
String.Format(
"
{0}\\{1}
"
, System.Configuration.ConfigurationSettings.AppSettings[
"
mediaPath
"
], media);
FileInfo fi
=
new
FileInfo(mediaFile);
if
(
!
fi.Exists)
throw
new
FileNotFoundException(
"
File does not exist: {0}. Check host configuration for 'mediaPath' setting.
"
, media);
TraceStream traceStream
=
null
;
FileStream fs
=
null
;
try
{
fs
=
new
FileStream(mediaFile, FileMode.Open, FileAccess.Read, FileShare.Read);
traceStream
=
new
TraceStream(fs);
}
catch
{
if
(fs
!=
null
)
fs.Close();
}
return
traceStream;
}
}
}
TraceStream代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Diagnostics;
using
System.IO;
namespace
WcfServiceLibrary3
{
public
class
TraceStream : Stream
{
System.IO.Stream m_in
=
null
;
System.IO.Stream m_out
=
null
;
public
override
bool
CanRead
{
get
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
get_CanRead: {0}
"
, m_in.CanRead));
return
m_in.CanRead;
}
}
public
override
bool
CanSeek
{
get
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
get_CanSeek: {0}
"
, m_in.CanSeek));
return
m_in.CanSeek;
}
}
public
override
bool
CanWrite
{
get
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
get_CanWrite: {0}
"
, m_in.CanWrite));
return
m_in.CanWrite;
}
}
public
override
long
Length
{
get
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
get_Length: {0}
"
, m_in.Length));
return
m_in.Length;
}
}
public
override
void
SetLength(
long
val
)
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
SetLength({0})
"
, val));
m_in.SetLength(val);
}
public
override
long
Position
{
get
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
get_Position: {0}
"
, m_in.Position));
return
m_in.Position;
}
set
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
set_Position: {0}
"
, m_in.Position));
m_in.Position
=
value;
}
}
public
TraceStream(System.IO.Stream stream)
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
TraceStream created.
"
));
m_in
=
stream;
}
public
override
IAsyncResult BeginRead(
byte
[] buffer,
int
offset,
int
count,
AsyncCallback callback,
object
state
)
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
BeginRead(): offset({0}), count({1})
"
, offset, count));
return
m_in.BeginRead(buffer, offset, count, callback, state);
}
public
override
IAsyncResult BeginWrite(
byte
[] buffer,
int
offset,
int
count,
AsyncCallback callback,
object
state
)
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
BeginWrite(): offset({0}), count({1})
"
, offset, count));
return
m_in.BeginWrite(buffer, offset, count, callback, state);
}
public
override
void
Close()
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
Close()
"
));
m_in.Close();
}
public
override
int
EndRead(
IAsyncResult asyncResult
)
{
Trace.WriteLine(
"
TraceStream
"
,
"
EndRead()
"
);
return
m_in.EndRead(asyncResult);
}
public
override
void
EndWrite(
IAsyncResult asyncResult
)
{
Trace.WriteLine(
"
TraceStream
"
,
"
EndWrite()
"
);
m_in.EndWrite(asyncResult);
}
public
override
void
Flush()
{
Trace.WriteLine(
"
TraceStream
"
,
"
Flush()
"
);
m_in.Flush();
}
public
override
long
Seek(
long
offset,
SeekOrigin origin
)
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
Seek(): offset({0}), origin({1})
"
, offset, origin));
return
m_in.Seek(offset, origin);
}
public
override
int
Read(
byte
[] buffer,
int
offset,
int
count)
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
Read(): offset({0}), count({1})
"
, offset, count));
return
m_in.Read(buffer, offset, count);
}
public
override
void
Write(
byte
[] buffer,
int
offset,
int
count
)
{
Trace.WriteLine(
"
TraceStream
"
, String.Format(
"
Write(): offset({0}), count({1})
"
, offset, count));
m_in.Write(buffer, offset, count);
}
}
}
App.config 代码
<?
xml version="1.0" encoding="utf-8"
?>
<
configuration
>
<
system.web
>
<
compilation
debug
="true"
/>
</
system.web
>
<
appSettings
>
<
add
key
="mediaPath"
value
="D:\omps-liucha-01.Bak\WCF\5\WebCast20071101_Demo\Streaming_WithTrace"
/>
</
appSettings
>
<!--
When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries.
-->
<
system.serviceModel
>
<
services
>
<
service
behaviorConfiguration
="WcfServiceLibrary3.Service1Behavior"
name
="WcfServiceLibrary3.MediaMangerService"
>
<
endpoint
address
="MediaManager"
binding
="basicHttpBinding"
contract
="WcfServiceLibrary3.IMediaManagerService"
/>
<!--
<endpoint address="MediaStream" contract="WcfServiceLibrary3.IMediaStreaming" binding="basicHttpBinding" bindingConfiguration="basicHttpStreaming"/>
-->
<
endpoint
address
="MediaStream"
contract
="WcfServiceLibrary3.IMediaStreaming"
binding
="netTcpBinding"
bindingConfiguration
="netTcpStreaming"
/>
<
endpoint
address
="mex"
binding
="mexHttpBinding"
contract
="IMetadataExchange"
/>
<
host
>
<
baseAddresses
>
<
add
baseAddress
="http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary3/Service1/"
/>
<
add
baseAddress
="net.tcp://localhost:9000"
/>
</
baseAddresses
>
</
host
>
</
service
>
</
services
>
<
bindings
>
<
netTcpBinding
>
<
binding
name
="netTcpStreaming"
transferMode
="StreamedRequest"
maxReceivedMessageSize
="40000000"
maxBufferSize
="4096"
sendTimeout
="00:00:15"
>
</
binding
>
</
netTcpBinding
>
<
basicHttpBinding
>
<
binding
name
="basicHttpStreaming"
messageEncoding
="Mtom"
maxReceivedMessageSize
="40000000"
transferMode
="Streamed"
>
</
binding
>
</
basicHttpBinding
>
</
bindings
>
<
behaviors
>
<
serviceBehaviors
>
<
behavior
name
="WcfServiceLibrary3.Service1Behavior"
>
<!--
To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment
-->
<
serviceMetadata
httpGetEnabled
="True"
/>
<!--
To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information
-->
<
serviceDebug
includeExceptionDetailInFaults
="False"
/>
</
behavior
>
</
serviceBehaviors
>
</
behaviors
>
</
system.serviceModel
>
</
configuration
>
上面这个Demo主要演示了流的邦定,大家可以重点关注一下Config文件里的highlight内容。
Demo3:WSDual 用于回调callback
MyService 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.ServiceModel;
namespace
WcfServiceLibrary4
{
[ServiceContract(Namespace
=
"
http://cnblogs.cn/charlesliu
"
, CallbackContract
=
typeof
(IHelloIndidoServiceCallback))]
public
interface
IMyService
{
[OperationContract(IsOneWay
=
true
)]
void
HelloIndigo(
string
message);
[OperationContract]
void
HelloIndigo2(
string
message);
}
public
interface
IHelloIndidoServiceCallback
{
[OperationContract(IsOneWay
=
true
)]
void
HelloIndigoCallback(
string
message);
[OperationContract]
void
HelloIndigoCallback2(
string
message);
}
[ServiceBehavior(ConcurrencyMode
=
ConcurrencyMode.Reentrant)]
public
class
MyService : IMyService
{
public
void
HelloIndigo(
string
message)
{
IHelloIndidoServiceCallback callback
=
OperationContext.Current.GetCallbackChannel
<
IHelloIndidoServiceCallback
>
();
callback.HelloIndigoCallback(message);
}
public
void
HelloIndigo2(
string
message)
{
IHelloIndidoServiceCallback callback
=
OperationContext.Current.GetCallbackChannel
<
IHelloIndidoServiceCallback
>
();
callback.HelloIndigoCallback2(message);
}
}
}
config 代码
<?
xml version="1.0" encoding="utf-8"
?>
<
configuration
>
<
system.web
>
<
compilation
debug
="true"
/>
</
system.web
>
<!--
When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries.
-->
<
system.serviceModel
>
<
services
>
<
service
name
="WcfServiceLibrary4.MyService"
behaviorConfiguration
="WcfServiceLibrary4.Service1Behavior"
>
<
host
>
<
baseAddresses
>
<
add
baseAddress
= "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary4/Service1/"
/>
</
baseAddresses
>
</
host
>
<!--
Service Endpoints
-->
<!--
Unless fully qualified, address is relative to base address supplied above
-->
<
endpoint
address
=""
binding
="wsDualHttpBinding"
contract
="WcfServiceLibrary4.IMyService"
>
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<
identity
>
<
dns
value
="localhost"
/>
</
identity
>
</
endpoint
>
<!--
Metadata Endpoints
-->
<!--
The Metadata Exchange endpoint is used by the service to describe itself to clients.
-->
<!--
This endpoint does not use a secure binding and should be secured or removed before deployment
-->
<
endpoint
address
="mex"
binding
="mexHttpBinding"
contract
="IMetadataExchange"
/>
</
service
>
</
services
>
<
bindings
>
<
wsDualHttpBinding
>
<
binding
name
="wsDualUsername"
maxReceivedMessageSize
="100000"
transactionFlow
="true"
>
<
readerQuotas
maxArrayLength
="100000"
maxStringContentLength
="100000"
/>
<
security
>
<
message
clientCredentialType
="UserName"
/>
</
security
>
</
binding
>
</
wsDualHttpBinding
>
</
bindings
>
<
behaviors
>
<
serviceBehaviors
>
<
behavior
name
="WcfServiceLibrary4.Service1Behavior"
>
<!--
To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment
-->
<
serviceMetadata
httpGetEnabled
="True"
/>
<!--
To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information
-->
<
serviceDebug
includeExceptionDetailInFaults
="False"
/>
<
serviceCredentials
>
<
serviceCertificate
findValue
="RPKey"
storeLocation
="LocalMachine"
storeName
="My"
x509FindType
="FindBySubjectName"
/>
</
serviceCredentials
>
</
behavior
>
</
serviceBehaviors
>
</
behaviors
>
</
system.serviceModel
>
</
configuration
>
client 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Threading;
using
System.ServiceModel;
using
ConsoleApplication1.MyServiceReference;
namespace
ConsoleApplication1
{
class
Program : IMyServiceCallback
{
static
void
Main(
string
[] args)
{
Console.WriteLine(
"
Client running on thread {0}
"
, Thread.CurrentThread.GetHashCode());
Console.WriteLine();
Program p
=
new
Program();
InstanceContext context
=
new
InstanceContext(p);
using
(MyServiceReference.MyServiceClient proxy
=
new
ConsoleApplication1.MyServiceReference.MyServiceClient(context))
{
WSDualHttpBinding b
=
proxy.Endpoint.Binding
as
WSDualHttpBinding;
b.ClientBaseAddress
=
new
Uri(
"
http://localhost:8100
"
);
//
Enter valid windows credentials here
Console.WriteLine();
Console.Write(
"
Enter username:
"
);
string
username
=
Console.ReadLine();
Console.Write(
"
Enter password:
"
);
Console.ForegroundColor
=
ConsoleColor.Black;
string
password
=
Console.ReadLine();
Console.ForegroundColor
=
ConsoleColor.White;
proxy.ClientCredentials.UserName.UserName
=
username;
proxy.ClientCredentials.UserName.Password
=
password;
Console.WriteLine();
Console.WriteLine(
"
Calling HelloIndigo() - one-way
"
);
proxy.HelloIndigo(
"
Hello from client.
"
);
Console.WriteLine(
"
Returned from HelloIndigo()
"
);
Console.WriteLine(
"
Calling HelloIndigo2() - not one-way
"
);
proxy.HelloIndigo2(
"
Hello from client.
"
);
Console.WriteLine(
"
Returned from HelloIndigo2()
"
);
Console.ReadLine();
}
}
public
void
HelloIndigoCallback(
string
message)
{
Console.WriteLine(
"
HelloIndigoCallback on thread {0} - one-way
"
, Thread.CurrentThread.GetHashCode());
}
public
void
HelloIndigoCallback2(
string
message)
{
Console.WriteLine(
"
HelloIndigoCallback2 on thread {0} - not one-way
"
, Thread.CurrentThread.GetHashCode());
}
}
}
对于WSDual邦定,有几点值得注意。CallbackContract的类名称在客户端会变,比如本例中的IHelloIndidoServiceCallback就变成了IMyServiceCallback。要想成功运行本例还要添加X509的证书,可以从http://www.dasblonde.net/downloads/code/CertificatesSetup.zip下载。WSDual的作用就是实现回调,客户端发送一个调用服务的方法的请求,服务器通过回调客户的方法,实际上也就是服务端调用了客户端的方法。同时这个Demo也展示了如何配置证书认证的配置方法。
Demo4:自定义邦定custombinding有配置文件实现
其实Demo1就是用自定义邦定来实现的,对一邦定使用时非常灵活,所以主要是掌握它的方法。
Service 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Runtime.Serialization;
using
System.ServiceModel;
using
System.Text;
namespace
WcfServiceLibrary5
{
[ServiceContract]
public
interface
IMyService
{
[OperationContract]
string
Hello(
string
message);
}
public
class
MyService : IMyService
{
public
string
Hello(
string
message)
{
return
message
+
"
Charles
"
;
}
}
}
Config 代码
<?
xml version="1.0" encoding="utf-8"
?>
<
configuration
>
<
system.web
>
<
compilation
debug
="true"
/>
</
system.web
>
<!--
When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries.
-->
<
system.serviceModel
>
<
services
>
<
service
name
="WcfServiceLibrary5.MyService"
behaviorConfiguration
="WcfServiceLibrary5.Service1Behavior"
>
<
host
>
<
baseAddresses
>
<
add
baseAddress
= "http://localhost:8001"
/>
</
baseAddresses
>
</
host
>
<!--
Service Endpoints
-->
<!--
Unless fully qualified, address is relative to base address supplied above
-->
<
endpoint
address
=""
binding
="customBinding"
contract
="WcfServiceLibrary5.IMyService"
bindingConfiguration
="customHttp"
>
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<
identity
>
<
dns
value
="localhost"
/>
</
identity
>
</
endpoint
>
<!--
Metadata Endpoints
-->
<!--
The Metadata Exchange endpoint is used by the service to describe itself to clients.
-->
<!--
This endpoint does not use a secure binding and should be secured or removed before deployment
-->
<
endpoint
address
="mex"
binding
="mexHttpBinding"
contract
="IMetadataExchange"
/>
</
service
>
</
services
>
<
bindings
>
<
customBinding
>
<
binding
name
="customHttp"
>
<
transactionFlow
transactionProtocol
="WSAtomicTransactionOctober2004"
/>
<
reliableSession
ordered
="true"
/>
<
textMessageEncoding
messageVersion
="Soap12WSAddressing10"
writeEncoding
="utf-8"
/>
<
httpTransport
/>
</
binding
>
</
customBinding
>
</
bindings
>
<
behaviors
>
<
serviceBehaviors
>
<
behavior
name
="WcfServiceLibrary5.Service1Behavior"
>
<!--
To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment
-->
<
serviceMetadata
httpGetEnabled
="True"
/>
<!--
To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information
-->
<
serviceDebug
includeExceptionDetailInFaults
="False"
/>
</
behavior
>
</
serviceBehaviors
>
</
behaviors
>
</
system.serviceModel
>
</
configuration
>
注意:<httpTransport />不是<httpsTransport />,搞了半天终于发现是这个问题。
Demo5:代码方式实现的邦定
Service 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.ServiceModel;
namespace
Helloindigo
{
[ServiceContract(Namespace
=
"
http://cnbolgs.com/charles
"
)]
public
interface
IHelloIndigoService
{
[OperationContract]
string
HelloIndigo(
string
messsage);
}
public
class
HelloIndigoService : IHelloIndigoService
{
public
string
HelloIndigo(
string
messsage)
{
return
messsage
+
"
Charles
"
;
}
}
}
Host 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.ServiceModel;
using
System.ServiceModel.Channels;
using
Helloindigo;
namespace
Host
{
class
Program
{
static
void
Main(
string
[] args)
{
using
(ServiceHost host
=
new
ServiceHost(
typeof
(HelloIndigoService),
new
Uri(
"
http://localhost:8000
"
)))
{
BindingElementCollection elements
=
new
BindingElementCollection();
elements.Add(
new
TransactionFlowBindingElement(TransactionProtocol.WSAtomicTransactionOctober2004));
elements.Add(
new
ReliableSessionBindingElement(
true
));
elements.Add(
new
TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8));
elements.Add(
new
HttpTransportBindingElement());
CustomBinding binding
=
new
CustomBinding(elements);
host.AddServiceEndpoint(
typeof
(IHelloIndigoService), binding,
"
HelloIndigoService
"
);
host.Open();
Console.WriteLine();
Console.WriteLine(
"
Press <ENTER> to terminate the host application
"
);
Console.Read();
}
}
}
}
Client 代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.ServiceModel;
using
System.ServiceModel.Channels;
namespace
Client
{
class
Program
{
static
void
Main(
string
[] args)
{
BindingElementCollection elements
=
new
BindingElementCollection();
elements.Add(
new
TransactionFlowBindingElement(TransactionProtocol.WSAtomicTransactionOctober2004));
elements.Add(
new
ReliableSessionBindingElement(
true
));
elements.Add(
new
TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8));
elements.Add(
new
HttpTransportBindingElement());
CustomBinding binding
=
new
CustomBinding(elements);
ChannelFactory
<
IHelloIndigoService
>
factory
=
new
ChannelFactory
<
IHelloIndigoService
>
(binding,
"
http://localhost:8000/HelloIndigoService
"
);
IHelloIndigoService proxy
=
null
;
try
{
proxy
=
factory.CreateChannel();
string
s
=
proxy.HelloIndigo(
"
Hello
"
);
Console.WriteLine(s);
Console.Read();
}
catch
(Exception ex)
{
Console.WriteLine(ex);
}
finally
{
ICommunicationObject obj
=
proxy
as
ICommunicationObject;
if
(obj
!=
null
)
{
obj.Close();
}
}
}
}
[ServiceContract(Namespace
=
"
http://cnbolgs.com/charles
"
)]
public
interface
IHelloIndigoService
{
[OperationContract]
string
HelloIndigo(
string
messsage);
}
}
这个Demo使用纯代码的方式实现邦定,但是相比之下用config的方式更简单更高效。
好,看了这么多的Demo大家对Binding应该有所了解了,下面把WCF Binding这部分总结讲解一下:
什么是绑定(Binding)?
• 绑定表示通讯信道(communication channel)的配置
• 绑定定义了客户端与服务端之间通讯的协议
– 传输协议
– 消息编码
– 安全性,可靠性消息与事务

1 Message Transmission Optimization Mechanism (MTOM)
2 Transmission Control Protocol (TCP)
3 Microsoft Message Queuing (MSMQ)
传输协议
• HTTP
• TCP
• 命名管道(Named Pipes)
• MSMQ
• 提供自定义协议的支持:UDP 或者 SMTP, 等等
消息编码
• Text
• MTOM
• Binary
• 能够提供自定义消息编码格式
其它的绑定协议
• 安全
–相互认证证书 (用于不同公司之间或是不同部门之间,提供一种相互的认证手段)
• X.509
–消息保护
• 可靠的消息
• 事务支持
• 能够使用自定义绑定协议进行扩展
信道(Channels)
• 信道栈在通讯的每个端点之间发送或者接收消息
– 客户端代理是从客户端绑定配置构建出来的信道
– ServiceHost根据服务绑定的配置,为每个端点暴露出信道的监听器
• 信道栈由绑定的元素组成

绑定元素
• 绑定(Binding)由绑定元素组成
• 每个绑定元素对于信道(channel)栈的某些部分进行配置
• 与端点(endpoint)相关
• 能够通过声明或在代码中对每个端点进行配置
选择绑定
• 标准绑定:
–预定义的绑定元素
– 为在HTTP, TCP, 命名管道或者MSMQ通讯上提供缺省设置
– 能够修改配置
• 自定义绑定:
– 完全自定义的绑定元素的集合
– 当标准绑定无法满足需求时使用
标准绑定
• BasicHttpBinding
• WSHttpBinding
• WSDualHttpBinding
• WSFederationHttpBinding
• NetNamedPipeBinding
• NetTcpBinding
• NetPeerTcpBinding
• NetMsmqBinding
• MsmqIntegrationBinding
Web Service绑定
• BasicHttpBinding与SOAP 1.1兼容
• WSHttpBinding与带有WS*的SOAP 1.2兼容
• WSDualHttpBinding适用于在支持WS*的HTTP协议上的回调(无法进行互操作)
• WSFederationHttpBinding适用于联合安全与单点登陆(SSO)的场景
跨进程/主机绑定
• NetNamedPipeBinding用于进程内或者同主机的调用
• NetTcpBinding用于同主机或者跨主机的调用
• NetPeerTcpBinding用于同主机或者跨主机点对点消息
消息绑定
• NetMsmqBinding用于在MSMQ上可靠的,事务的并且持久的消息
• MsmqIntegrationBinding用于早期技术的MSMQ互操作
自定义标准绑定
代码
<
system.serviceModel
>
<
services
>
<
service
name
="HelloIndigo.HelloIndigoService"
>
<
endpoint
binding
="netTcpBinding"
bindingConfiguration
="netTcp"
contract
="HelloIndigo.IHelloIndigoService"
/>
</
service
>
</
services
>
<
bindings
>
<
netTcpBinding
>
<
binding
name
="netTcp"
maxReceivedMessageSize
="5000000"
>
<
security
mode
="Message"
>
<
message
clientCredentialType
="Windows"
/>
</
security
>
</
binding
>
</
netTcpBinding
>
</
bindings
>
</
system.serviceModel
>
创建自定义绑定
代码
<
system.serviceModel
>
<
services
>
<
service
name
="HelloIndigo.HelloIndigoService"
>
<
endpoint
binding
="customBinding"
bindingConfiguration
="custom"
contract
="HelloIndigo.IHelloIndigoService"
/>
</
service
>
</
services
>
<
bindings
>
<
customBinding
>
<
binding
name
="custom"
>
<
security
authenticationMode
="SspiNegotiated"
>
<
localServiceSettings
detectReplays
="true"
/>
</
security
>
<
textMessageEncoding
/>
<
httpTransport
maxReceivedMessageSize
="5000000"
/>
</
binding
>
</
customBinding
>
</
bindings
>
</
system.serviceModel
>
(完)