Monday, November 2, 2009

The Service Bus (within Microsoft's new .NET Services product) is a nice bit of technology that allows two-way communication between nodes on the Internet, regardless of the presence of firewalls, NAT gateways or other complicated network topologies. It makes possible all sorts of useful tools, such as Rich's and Rob's SocketShifter.

What's really nice about Service Bus's implementation, however, (and often overlooked) is that it's nothing more than a new set of WCF bindings which result in the creation of publicly reachable and discoverable endpoints.

With that in mind, I wondered whether I could take my previous simple WCF example, and change it to use the Service Bus by doing nothing more than modifying the config. In theory, it seems that this should be possible once the Service Bus becomes a standard part of the .NET framework - but for now it proves difficult. This is because installing the .NET Services CTP will modify your machine.config file such that netTcpRelayBinding cannot be added again as an extension within an app.config, but HAS to be added in that way for machines without the CTP installed (i.e. all of your customers' servers, or indeed an Azure VM).

The only sensible way to achieve this, therefore, is by explicitly setting options within the code itself - but this proved pretty easy.

Messaging Model

Let's start by modifying the code of the previous example slightly so that we emphasise the delivery of a message and a reply. We'll make the GetTimestamp method take a string, which gets printed at the server and copied back within the reply:

Configure the endpoint of the ClientBase class we're inheriting from on construction, to ensure we only do it once:

(Assembly reference: Microsoft.ServiceBus)

using Microsoft.ServiceBus;

...

public HealthCheck()

{

// Construct EndpointBehaviour for SB username and password

TransportClientEndpointBehavior serviceBusCredential =

newTransportClientEndpointBehavior();

serviceBusCredential.CredentialType =

TransportClientCredentialType.UserNamePassword;

serviceBusCredential.Credentials.UserName.UserName = "yourAccount";

serviceBusCredential.Credentials.UserName.Password = "yourPassword";

// Set the binding manually (overriding the app.config)

this.Endpoint.Address = newEndpointAddress(

"sb://yourAccount.servicebus.windows.net/test/");

this.Endpoint.Binding = newNetTcpRelayBinding();

this.Endpoint.Behaviors.Add(serviceBusCredential);

}

That's it! If you fire up the server and the client, you should now see them working exactly as before - except you can now have the server running on your home machine behind a NAT gateway, and the client running on your office machine behind a corporate firewall!