Declaritively and Programitcally Subscribing to the Windows Azure Service Bus Relay with WCF

Preferably I like to have most of the configuration for WCF in my config file(s), however when PoC’ing and time is of essence, spending time troubleshooting your config file(s) can be frustrating, for example:

Web.config ‘TransportClientEndPointBehavior‘ element is not recognized when trying to configure your service/application to wire up to Windows Azure Service Bus so that you can push messages on to it, so that you can start relaying.

Error squiggly (message):

“The element ‘behavior’ has invalid child element ‘transportClientEndpointBehavior’. List of possible elements expected: ‘clientVia, callbackDebug, callbackTimeouts, clear, clientCredentials, transactedBatching, dataContractSerializer, dispatcherSyncronization, remove, synchronousRecieve, enableWebScript, webHttp, endpointDiscovery, soapProcessing’.”

Spent some time Googling and regretfully didn’t find any documentation out there on how subscribe to Windows Azure Service Bus 100% programitcally, so hence this blog post. So, let’s get started on how to wire up to Azure’s Service Bus with both approaches.

If you need to know how to setup the Windows Azure Service Bus in the Azure Portal please read https://www.windowsazure.com/en-us/develop/net/how-to-guides/service-bus-relay/.

First, let’s review how to push messages onto the Windows Azure Service Bus for relaying.

Programitically (zero configuration in your .config file)

  • Create an interface that implements IAzureTunnelService, IClientChannel.

    
        public interface IAzureTunnelServiceChannel : IAzureTunnelService, IClientChannel
        {
        }
    
    
  • Wire up to push messages on Windows Azure Service Bus for relay.

    
                var serviceUri = ServiceBusEnvironment
                    .CreateServiceUri("sb", "yournamespace", "relaystatus");
    
                var sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();
    
                var tokenProvider = TokenProvider
                    .CreateSharedSecretTokenProvider("owner", "secretkey");
    
                sharedSecretServiceBusCredential.TokenProvider = tokenProvider;
    
                var endpoint = new ServiceEndpoint(
                    ContractDescription.GetContract(typeof(IAzureTunnelService)),
                    new NetTcpRelayBinding(
                        EndToEndSecurityMode.Transport, 
                        RelayClientAuthenticationType.None),
                        new EndpointAddress(serviceUri));
    
                var channelFactory = new ChannelFactory<IAzureTunnelService>(endpoint);
                channelFactory.Endpoint.Behaviors.Add(sharedSecretServiceBusCredential);
                var channel = channelFactory.CreateChannel();
                var result = channel.RelayRequest(yourmodel);
    
    

Declaritively

  • web.config/app.config (system.serviceModel section)

    In the config we are introducing all known service bus extensions. You can remove the ones you don’t need.

    
      <system.serviceModel>
        <client>
          <endpoint name="relayrequest" contract="YourNameSpace.AzureTunnel.Common.Contracts.IAzureTunnelService" binding="netTcpRelayBinding" address="sb://yourSBnamespace.servicebus.windows.net/relayrequest" behaviorConfiguration="sbTokenProvider" />
        </client>
        <behaviors>
          <endpointBehaviors>
            <behavior name="sbTokenProvider">
              <transportClientEndpointBehavior>
                <tokenProvider>
                  <sharedSecret issuerName="owner" issuerSecret="yoursecretykeygoeshere" />
                </tokenProvider>
              </transportClientEndpointBehavior>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
        <extensions>
          <!-- In this extension section we are introducing all known service bus extensions. User can remove the ones they don't need. -->
          <behaviorExtensions>
            <add name="connectionStatusBehavior" type="Microsoft.ServiceBus.Configuration.ConnectionStatusElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="serviceRegistrySettings" type="Microsoft.ServiceBus.Configuration.ServiceRegistrySettingsElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          </behaviorExtensions>
          <bindingElementExtensions>
            <add name="netMessagingTransport" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="tcpRelayTransport" type="Microsoft.ServiceBus.Configuration.TcpRelayTransportElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="httpRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpRelayTransportElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="httpsRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpsRelayTransportElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="onewayRelayTransport" type="Microsoft.ServiceBus.Configuration.RelayedOnewayTransportElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          </bindingElementExtensions>
          <bindingExtensions>
            <add name="basicHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.BasicHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="webHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="ws2007HttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WS2007HttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="netTcpRelayBinding" type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="netOnewayRelayBinding" type="Microsoft.ServiceBus.Configuration.NetOnewayRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="netEventRelayBinding" type="Microsoft.ServiceBus.Configuration.NetEventRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          </bindingExtensions>
        </extensions>
      </system.serviceModel>
    
    
  • C# Code

    
                var channelFactory = new ChannelFactory<IAzureTunnelServiceChannel>("relayrequest");
                using (var channel = channelFactory.CreateChannel())
                {
                    return channel.RelayRequest(url, myModel);
                }
    
    

Note: To shortcut some of this configuration you can add the appropriate references and config configurations by using NuGet and installing the Windows Azure Service Bus package.


Finally, let’s wire up to receive messages off the Windows Azure Service Bus that we relayed earlier (consumer, demonstrated with a console app) programatically.

  • Service Interface

    
        [ServiceContract(Namespace = "urn:ps")]
        public interface IAzureTunnelService
        {
            [OperationContract]
            XElement RelayRequest(string url, YourModel yourModel);
        }
    
    
  • Service Implementation

    
        public class AzureTunnelService : IAzureTunnelService
        {
            public XElement RelayRequest(string url, YourModel yourModel)
            {
                Console.WriteLine("{0,13}|{1,13}", 
                  yourModel.yourProperty1, 
                  yourModel.yourProperty2);
            }
        }
    
    
  • Host the WCF Service

    
            private static void Main(string[] args)
            {
                var serviceHost = new ServiceHost(typeof (AzureTunnelService));
    
                serviceHost.AddServiceEndpoint(
                    typeof (IAzureTunnelService), 
                    new NetTcpBinding(), "net.tcp://localhost:9385/relayrequest");
    
                serviceHost.AddServiceEndpoint(
                    typeof(IAzureTunnelService), 
                    new NetTcpRelayBinding(),
                    ServiceBusEnvironment
                        .CreateServiceUri("sb", "yourSBnamespace", "relayrequest"))
                        .Behaviors.Add(new TransportClientEndpointBehavior
                            {
                                TokenProvider = TokenProvider
                                    .CreateSharedSecretTokenProvider(
                                        "owner", 
                                        "yoursecretkey"
                                    )
                            });
    
                serviceHost.Open();
                Console.WriteLine("Press ENTER to close.");
                Console.ReadLine();
                serviceHost.Close();
            }
    
    

Yes, we have configuration in code, however push comes to shove, it’s always good to have an alternative solution. Being pragmatic about this, how often are you going to need to change your configuration on how your are communicating with Windows Azure Service Bus anyway?

Happy Coding…! :)

About these ads

2 thoughts on “Declaritively and Programitcally Subscribing to the Windows Azure Service Bus Relay with WCF

  1. Hi Lee,

    I have an WCF using the azure service bus, my config file looks same to yours.

    However, it looks like the transportClientEndpointBehavior doesn’t work in Azure. It does in my box.
    Any advise?

    Thanks

    Like

  2. Pingback: code generate Azure Servicebus Namespace - Windows Azure Blog

Comments are closed.