wsDualHttpBinding
The wsDualHttpBinding binding is similar to the wsHttpBinding binding, with additional support for duplex communication and lack of support for transport-level security. Duplex communication is accomplished through two shape-changing binding elements: the OneWayBindingElement and CompositeDuplexBindingElement binding elements. The CompositeDu-plexBindingElement binding element layers a duplex communication channel on top of two one-way channels. The wsDualHttpBinding binding uses the HttpTransportBindingElement binding element. This transport supports only the request-reply message exchange pattern. The OneWayBindingElement binding element allows the HttpTransportBindingElement binding element to be used with the CompositeDuplexBindingElement binding element.
The wsDualHttpBinding binding does not support transport-level security. This means that SSL/TLS encryption is not possible using the wsDualHttpBinding binding.
The following code shows the addressing formats for the wsDualHttp-Binding binding.
http://{hostname}:{port}/{service location}
The default port is port 80 for http. This is the case for any binding based on the HttpTransportBindingElement binding element, including the wsDualHttpBinding binding.
Table 4.10 lists the binding properties that are configurable on the wsDualHttpBinding binding.
|
Attribute Name |
Description |
Default |
|
bypassProxyOnLocal |
Bypass the proxy settings for local endpoints. |
false |
|
closeTimeout |
The maximum time to wait for the connection to be closed. |
00:01:00 |
|
hostNameComparisonMode |
Specifies the method for hostname comparison when parsing URIs. |
StrongWildCard |
|
maxBufferPoolSize |
Maximum size of any buffer pools used by the transport. |
524,888 |
|
maxReceivedMessageSize |
The maximum size of an incoming message. |
65,536 |
|
messageEncoding |
The type of encoding used to encode messages. |
Text |
|
name |
The name of the binding. | |
|
openTimeout |
The maximum time to wait for an open connection operation to complete. |
00:01:00 |
|
Attribute Name |
Description |
Default |
|
proxyAddress |
Specify a specific Web proxy to use. useDefaultWebProxy must be false for this setting to apply. |
n/a |
|
readerQuotas |
Specify the complexity of messages that can be processed (for example, size). |
n/a |
|
receiveTimeout |
The maximum time to wait for a receive operation to complete. |
00:01:00 |
|
reliableSession |
Specify whether the binding supports exactly once delivery assurances using WS-Reliable Messaging. |
n/a |
|
security |
Specifies the security settings of the binding. |
n/a |
|
sendTimeout |
The maximum time to wait for a send operation to complete. |
00:01:00 |
|
textEncoding |
Determines how messages are sent across the network. Messages can either be buffered or streamed. |
utf-8 |
|
transactionFlow |
Enable transactions to flow from the client to the server. |
false |
|
useDefaultWebProxy |
Use the default Web proxy specified by the operating system. |
true |
We have modified the StockQuoteService application for the wsDualHttp-Binding binding to support duplex communication. Listing 4.17 shows the StockQuoteDuplexService implementation. The service supports the duplex message exchange pattern using the IStockQuoteCallback contract, which is the callback contract specified for the IStockQuoteDuplexService contract.
Listing 4.17 IStockQuoteDuplexService, IStockQuoteCallback, and StockQuoteDuplexService using System;
using System.Collections.Generic; using System.ServiceModel; using System.Text;
namespace EssentialWCF {
[ServiceContract(CallbackContract = typeof(IStockQuoteCallback), SessionMode = SessionMode.Required)]
public interface IStockQuoteDuplexService {
[OperationContract(IsOneWay = true)] void SendQuoteRequest(string symbol);
public interface IStockQuoteCallback {
[OperationContract(IsOneWay = true)]
void SendQuoteResponse(string symbol, double price);
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class StockQuoteDuplexService : IStockQuoteDuplexService {
public void SendQuoteRequest(string symbol) {
double value;
value = 31.15; else if (symbol == "YHOO")
value = 28.10; else if (symbol == "GOOG") value = 450.75;
else value = double.NaN;
OperationContext ctx = OperationContext.Current; IStockQuoteCallback callback = ctx.GetCallbackChannel<IStockQuoteCallback>();
callback.SendQuoteResponse(symbol, value);
We must change the self-hosting code for our example because we changed the implementation that we are using to one that supports duplex messaging. Listing 4.18 shows the hosting code for the StockQuoteDu-plexService service.
Listing 4.18 StockQuoteDuplexService ServiceHost Service using System;
using System.Collections.Generic; using System.Configuration; using System.Text; using System.ServiceModel;
namespace EssentialWCF {
internal class MyServiceHost {
internal static ServiceHost myServiceHost = null;
internal static void StartService() {
myServiceHost =
new ServiceHost(typeof(EssentialWCF.StockQuoteDuplexService)); myServiceHost.Open();
internal static void StopService() {
if (myServiceHost.State != CommunicationState.Closed) myServiceHost.Close();
The configuration information shown in Listing 4.19 exposes the StockQuoteDuplexService service using the wsDualHttpBinding binding.
Listing 4.19 wsDualHttpBinding Host Configuration
<?xml version="1.0" encoding="utf-8" ?> <configuration>
<system.serviceModel> <services>
<service name="EssentialWCF.StockQuoteDuplexService"> <host>
<baseAddresses>
<add baseAddress="http://localhost/stockquoteservice" />
Listing 4.19 continued
<endpoint address=""
binding="wsDualHttpBinding"
contract="EssentialWCF.IStockQuoteDuplexService"> </endpoint> </service> </services> </system.serviceModel> </configuration>
The configuration information shown in Listing 4.20 is for the client to consume a service based on the IStockQuoteDuplexService contract using the wsDualHttpBindingbinding. The clientBaseAddress specifies the endpoint on which the client will listen for callback messages.
Listing 4.20 wsDualHttpBinding Client Configuration
<?xml version="1.0" encoding="utf-8" ?> <configuration>
<system.serviceModel> <client>
<endpoint address="http://localhost/stockquoteservice" binding="wsDualHttpBinding"
bindingConfiguration="SpecifyClientBaseAddress" contract="IStockQuoteDuplexService"> </endpoint> </client> <bindings>
<wsDualHttpBinding>
<binding name="SpecifyClientBaseAddress"
clientBaseAddress="http://localhost:8001/client/" /> </wsDualHttpBinding> </bindings> </system.serviceModel> </configuration>
The client application is shown in Listing 4.21. The client implements the IStockQuoteDuplexServiceCallback interface to receive callback messages from the service. The client application passes a reference to the IStockQuoteDuplexServiceCallback interface using the InstanceContext class. The InstanceContext class is passed to the constructor of the client proxy.
Listing 4.21 wsDualHttpBinding Client Application using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace EssentialWCF {
public class Program : IStockQuoteDuplexServiceCallback {
private static AutoResetEvent waitForResponse;
static void Main(string[] args) {
string symbol = "MSFT";
waitForResponse = new AutoResetEvent(false);
InstanceContext callbacklnstance =
new InstanceContext(new Program()); using (StockQuoteDuplexServiceClient client =
new StockQuoteDuplexServiceClient(callbacklnstance))
client.SendQuoteRequest(symbol); waitForResponse.WaitOne();
Console.ReadLine();
#region IStockQuoteDuplexServiceCallback Members public void SendQuoteResponse(string symbol, double price) {
Console.WriteLine("{0} @ ${1}", symbol, price); waitForResponse.Set();
#endregion
Listing 4.22 shows the client proxy generated by svcutil.exe. The big difference between this client proxy and the previous implementation is that the client derives from the DuplexClientBase class rather than the ClientBase class. The DuplexClientBase class adds support for duplex messaging.
Listing 4.22 wsDualHttpBinding Client Proxy using System.CodeDom.Compiler; using System.Diagnostics; using System.ServiceModel; using System.ServiceModel.Channels;
namespace EssentialWCF {
[GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] [ServiceContractAttribute(
ConfigurationName = "IStockQuoteDuplexService", CallbackContract = typeof(IStockQuoteDuplexServiceCallback), SessionMode = SessionMode.Required)]
public interface IStockQuoteDuplexService {
[OperationContractAttribute(IsOneWay = true,
Action="http://tempuri.org/IStockQuoteDuplexService/ ^•SendQuoteRequest")]
void SendQuoteRequest(string symbol);
[GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface IStockQuoteDuplexServiceCallback {
[OperationContractAttribute(IsOneWay = true,
Action="http://tempuri.org/IStockQuoteDuplexService/ ^•SendQuoteResponse")]
void SendQuoteResponse(string symbol, double price);
[GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] public interface IStockQuoteDuplexServiceChannel : IStockQuoteDuplexService, IClientChannel
[DebuggerStepThroughAttribute()]
[GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] public partial class StockQuoteDuplexServiceClient : DuplexClientBase<IStockQuoteDuplexService>,
IStockQuoteDuplexService public StockQuoteDuplexServiceClient(
InstanceContext callbacklnstance) : base(callbacklnstance)
public StockQuoteDuplexServiceClient(
InstanceContext callbacklnstance, string endpointConfigurationName) : base(callbackInstance, endpointConfigurationName)
public StockQuoteDuplexServiceClient(
InstanceContext callbacklnstance, string endpointConfigurationName, string remoteAddress) : base(callbackInstance, endpointConfigurationName, remoteAddress)
public StockQuoteDuplexServiceClient(
InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress) : base(callbackInstance, endpointConfigurationName, remoteAddress)
public StockQuoteDuplexServiceClient(
InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress) : base(callbackInstance, binding, remoteAddress)
public void SendQuoteRequest(string symbol) {
base.Channel.SendQuoteRequest(symbol);
Post a comment