ws2007HttpRelayBinding and Windows Azure Client
Recently we have faced this issue of not being able to consume a WCF service which was exposed using ws2007HttpRelayBinding from Windows Azure Web Role as a client. We had registered a service on AppFabric Service Bus with ws2007HttpRelayBinding; below is the service registration code for the service.
// create the service URI based on the service namespace
Uri address = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespace, "EchoService");
//// create the credentials object for the endpoint
TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();
sharedSecretServiceBusCredential.CredentialType = TransportClientCredentialType.SharedSecret;
sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerName = issuerName;
sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerSecret = issuerSecret;
WS2007HttpRelayBinding binding = new WS2007HttpRelayBinding(EndToEndSecurityMode.Transport, RelayClientAuthenticationType.None);
// create the service host reading the configuration
ServiceHost host = new ServiceHost(typeof(EchoService), address);
// create the ServiceRegistrySettings behavior for the endpoint
IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);
// add the Service Bus credentials to all endpoints specified in configuration
foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
{
endpoint.Binding = binding;
endpoint.Behaviors.Add(serviceRegistrySettings);
endpoint.Behaviors.Add(sharedSecretServiceBusCredential);
}
// open the service
host.Open();
Config Setting for Relay Endpoint
<services>
<!-- Application Service -->
<service name="Microsoft.ServiceBus.Samples.EchoService">
<!--<endpoint contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="netTcpRelayBinding" />-->
<endpoint contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="ws2007HttpRelayBinding" />
</service>
</services>
And we were consuming the above service in our client which was a Windows Azure Web Role application.
Client CodeUri serviceUri = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespace, "EchoService");
// create the channel factory loading the configuration
ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", new EndpointAddress(serviceUri));
IEchoChannel channel = channelFactory.CreateChannel();
channel.Open();
Client Config Setting
<client>
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="ws2007HttpRelayBinding"/>
</client>
So far so good, we tested this application on development fabric everything worked fine. Happy! Deployed to Windows Azure and gotcha!! Following exception
“Configuration binding extension 'system.serviceModel/bindings/ws2007HttpRelayBinding' could not be found. Verify that this binding extension is properly registered in system.serviceModel/extensions/bindingExtensions and that it is spelled correctly”
Reconfirmed the spelling (case) of the binding name, redeploying didn’t solve the issue; same error.
I came across an article on RelayConfigurationInstaller which says “The primary scenario for RelayConfigurationInstaller is to assist in installing the necessary Machine.config or App.config information necessary to run a AppFabric Service Bus application on a computer that does not have AppFabric Service Bus installed. However, in most scenarios, the application installer for the AppFabric Service Bus application would automatically install the necessary configuration information. Therefore, this API would likely be used by developer who want additional control over the installation process.”
I realized the machine.config settings for relay binding would not there on Windows Azure virtual machine but I didn’t prefer using relayconfigurationinstaller.exe or accessing it from object model.
There are two ways we could solve this problem:
1. Don’t use the client config settings in web role web.config file; instead provide all the binding related information as part of the code only, like
Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespace, "EchoService");
WS2007HttpRelayBinding binding = new WS2007HttpRelayBinding(EndToEndSecurityMode.Transport, RelayClientAuthenticationType.None);
ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>();
channelFactory.Endpoint.Address = new EndpointAddress(serviceUri);
channelFactory.Endpoint.Binding = binding;
IEchoChannel channel = channelFactory.CreateChannel();
channel.Open();
2. Don’t use relay binding at client side instead use the plain (without relay) binding.
Client CodeUri serviceUri = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespace, "EchoService");
ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", new EndpointAddress(serviceUri));
IEchoChannel channel = channelFactory.CreateChannel();
channel.Open();
Client Config Setting
<system.serviceModel><bindings>
<ws2007HttpBinding>
<binding name =" plainbindingconfig">
<security mode ="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</ws2007HttpBinding>
</bindings>
<client>
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="ws2007HttpBinding" bindingConfiguration ="plainbindingconfig" />
</client>
</system.serviceModel>
Notice the binding is “ws2007HttpBinding” and it uses binding configuration plainbindingconfig because we are exposing the service on https. If we don’t use the binding configuration we would get an error of doesn’t support https end point, supports only http.
We preferred second solution to first one. The reason is straight forward; we should be able to consume a service without using the relay binding. Relay binding is meant for registering a service on the Service Bus and consumption of the service should be transparent of Relay binding. This avoided the complications of using the relay binding at the client end.
Hope you find our learning helpful.



Comments
Hi Sachin,
Very nice article. It helped me to solve the issue related to service bus. We were using netTcpRelayBinding for the service as well as client and we got this error at azure client : System.Configuration.ConfigurationErrorsException: Invalid element in configuration. The extension name 'transportClientEndpointBehavior' is not registered in the collection at system.serviceModel/extensions/behaviorExtensions.
We did the changes as suggested here and could able to conenct to on premise wcf service.
Please let me know if any solution is there when we use netTcpRelayBinding.
Once again Thanks,
Kiran
Posted by: Kiran | July 14, 2010 11:33 AM
Hi Sachin,
Just wanted to let you know that your blog on the WS2007HttpRelayBinding was extremely helpful !
We read your blog a while back & in the process of debugging our code both Sourish and I remembered exactly where we were making a mistake, in the client config, while calling the service.
Thanks Again,
Uday (& Sourish) :)
Posted by: Uday Sagar N | October 28, 2010 12:21 PM
When you want a WCF Service consumer web role to run from cloud, you need to take some more steps. The consumer connects to your on-premise WCF service using netTcpRelayBinding. These steps are not required if you want to run the consumer on local dev server.
I tried the method explained on MSDN at http://msdn.microsoft.com/en-us/library/microsoft.servicebus.configuration.relayconfigurationinstaller.aspx, which explains that the tool named RelayConfigurationInstaller.exe needs to be run on VM as a startup task (on local machine, this tool is available in service bus SDK installation folder C:\Program Files\Windows Azure AppFabric SDK\V1.0\Assemblies\NET4.0). So I added the startup task to the role project config and re-deployed the package. Later, the consumer role came up and running and it also consumed on-premise WCF service running on my machine by connecting to service bus using net tcp relay binding. I also added to the role project the tool RelayConfigurationInstaller.exe and RelayConfigurationInstaller.exe.config so that these were available on the Azure VM.
Startup task:
Posted by: Prasad | November 25, 2011 1:17 PM