MULTIMEDIA

Programming the Service Bus

9/23/2010 3:06:06 PM
The service bus supports a WCF-friendly programming model by offering a set of dedicated bindings and behaviors. By and large, except for a few slight twists to the programming model, working with the relay service is no different from any other WCF service.

The service bus supports the core WCF features of reliable messaging, Message security and Transport security. Presently, it does not support propagation of transactions from the client to the service across the relay service.

The service bus features are available in the Microsoft.ServiceBus.dll assembly, mostly under the Microsoft.ServiceBus namespace.


Note: The service bus requires a separate download of the Windows Azure SDK, and will work on machines running .NET 3.5 and .NET 4.0.

1. Relay Service Address

After opening an account with the Windows Azure AppFabric Service Bus, you need to use the Windows Azure AppFabric Service Bus administration website to create a service namespace (see Figure 1) and to select a connection payment plan.

Figure 1. Creating a service namespace



Note: It may be obvious, yet it is best to state that the service bus use is not free and, at the time of this writing, users (both clients and services) pay based on the maximum number of active concurrent connections per unit of time they maintain against the service bus.

A service namespace is the equivalent of a machine or domain name in regular network addressing, and any available (not already taken) URI-compliant string will do.

Like any other WCF service, every relayed service must have a unique address. The format of the address is always a base address followed by any number of optional URIs:

[base address]/[optional URI]/.../[optional URI]

The format of the base address is always the transport scheme followed by the service namespace and then the service bus address:

[scheme]://[service namespace].[service bus address]

For now, the service bus address is always:

servicebus.windows.net

The format of the scheme is either sb, http, or https. Example 1 shows a few possible addresses.

Example 1. Possible service bus addresses
sb://MyNamespace.servicebus.windows.net/
sb://MyNamespace.servicebus.windows.net/MyService
sb://MyNamespace.servicebus.windows.net/MyService/MyEndpoint
sb://MyNamespace.servicebus.windows.net/AnythingYouLike

http://MyNamespace.servicebus.windows.net/
http://MyNamespace.servicebus.windows.net/MyService

https://MyNamespace.servicebus.windows.net/MyService/MyEndpoint
https://MyNamespace.servicebus.windows.net/AnythingYouLike

Once your service connects to the relay service and starts listening on its address, no other service can listen on any other URI scoped under your service URI. Put differently, two distinct services must have two addresses so that no address is the prefix of the other. For example, here are two invalid addresses when used concurrently:

sb://MyNamespace.servicebus.windows.net/
sb://MyNamespace.servicebus.windows.net/MyService

The address of the service bus is available via the ServiceBusEnvironment static class:

public static class ServiceBusEnvironment
{
public static Uri CreateServiceUri(string scheme,string serviceNamespace,
string servicePath);
public static string DefaultIdentityHostName
{get;}

//More members
}

string serviceBusAddress = ServiceBusEnvironment.DefaultIdentityHostName;
Debug.Assert(serviceBusAddress == "servicebus.windows.net");


1.1. Extracting the service namespace

When working with the service bus and a config file, you should avoid hard-coding the service namespace either on the client or the service. Instead, you can extract the service namespace from the config file using my ServiceBusHelper static helper class, shown in Example 2.

Example 2. Extracting the service namespace from the config file
public static class ServiceBusHelper
{
public static string ExtractNamespace(Uri address)
{
return address.Host.Split('.')[0];
}

public static string ExtractNamespace(string endpointName)
{
Configuration config =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ServiceModelSectionGroup sectionGroup =
ServiceModelSectionGroup.GetSectionGroup(config);

foreach(ChannelEndpointElement endpointElement in
sectionGroup.Client.Endpoints)
{
if(endpointElement.Name == endpointName)
{
return ExtractNamespace(endpointElement.Address);
}
}
return null;
}
public static string ExtractNamespace(Type serviceType)
{
Configuration config =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ServiceModelSectionGroup sectionGroup =
ServiceModelSectionGroup.GetSectionGroup(config);

foreach(ServiceElement serviceElement in sectionGroup.Services.Services)
{
if(serviceElement.Name == serviceType.ToString())
{
return ExtractNamespace(serviceElement.Endpoints[0].Address);
}
}
return null;
}
}


The client can provide the endpoint name to the ExtractNamespace() method, and the method will iterate over the client endpoints, parsing the service namespace out of the matching endpoint address. The host can call the ExtractNamespace() method while providing it the service type, in which case the method will parse the service namespace out of the first endpoint the host uses. You will see usage of these helper methods later in the chapter.

2. The Service Bus Registry

The service bus offers an ATOM feed of listening services on the service namespace base address or on any one of its sub-URIs. You can view the feed by navigating to the service namespace (or the nested URI) using a browser, as shown in Figure 2.

Figure 2. The service bus registry feed


By default, your service will not be listed in the service bus registry. You control the service registry publishing using the ServiceRegistrySettings endpoint behavior class, defined as:

public enum DiscoveryType
{
Public,
Private
}
public class ServiceRegistrySettings : IEndpointBehavior
{
public ServiceRegistrySettings();
public ServiceRegistrySettings(DiscoveryType discoveryType);

public DiscoveryType DiscoveryMode
{get;set;}
public string DisplayName
{get;set;}
}

The host needs to add that behavior programmatically to every endpoint you wish to publish to the registry (there is no matching configurable behavior). For example, use the following to publish all endpoints to the registry:

IEndpointBehavior registryBehavior =
new ServiceRegistrySettings(DiscoveryType.Public);

ServiceHost host = new ServiceHost(typeof(MyService));

foreach(ServiceEndpoint endpoint in host.Description.Endpoints)
{
endpoint.Behaviors.Add(registryBehavior);
}

host.Open();


You can streamline this behavior with a dedicated host type, such as my DiscoverableServiceHost:

public partial class DiscoverableServiceHost : ServiceHost,...
{
public DiscoverableServiceHost(Type serviceType,params Uri[] baseAddresses)
: base(serviceType,baseAddresses)
{}

//More constructors

protected override void OnOpening()
{
IEndpointBehavior registryBehavior = new
ServiceRegistrySettings(DiscoveryType.Public);

foreach(ServiceEndpoint endpoint in Description.Endpoints)
{
endpoint.Behaviors.Add(registryBehavior);
}
base.OnOpening();
}
}



3. The Service Bus Explorer

To help visualize the service bus, I wrote the Service Bus Explorer shown in Figure 3.

Figure 3. The Service Bus Explorer


The tool accepts the service namespace to explore and after logging into the feed will display the running services for you. All the explorer does is parse the ATOM feed and place the items in the tree on the left. You can explore multiple service namespaces and see your service bus administration pages in the right pane. The tool also shows the available buffers (discussed later in the chapter); this information is very handy in administering them.

Other  
 
Top 10
AVM Fritz! Box 3370 – Everything’s Networked with Fritz
The Real 3D Experience
Panasonic Toughbook CF-19 - Two Shall Never Meet
Sony Movie Studio Platinum 12 - A Lean, Mean Video-Editing Machine
Automation For The People
The Samsung GALAXY Camera - An All New Hybrid
PSB M4U 2 Headphones
New Gadgets For April 2013 (Part 3)
New Gadgets For April 2013 (Part 2)
New Gadgets For April 2013 (Part 1)
Most View
Gigabyte GA-F2A85X-UP4
Cheetah3D 6 : Britain's next top modeler
Using SQL Server 2005 Integration Services : Extensibility (part 4) - Custom Connection Managers
Philips 237E3QPH : A good example of a performing yet affordable IPS monitor
6 Ways To Program Your Life (Part 2)
Lenovo ThinkCentre M92/M92P Tiny - So Small You May Miss It
Windows Server 2003 : Implementing a GPO (part 2) - Modifying a GPO
Improvements in Windows Server 2008 R2 for Better Branch Office Support
Samsung NX20 Pros and Cons
Linux Software : Mint Debian
Gorilla Gondola
Exploring the T-SQL Enhancements in SQL Server 2005 : The PIVOT and UNPIVOT Operators
Philips 7000 Series 46PFL7007
The big test … Inter Core Power (Part 3) - HP DV7-6103ea & Packard Bell EasyNote TS13
Group Test: Eight Panels Beyond HD (Part 3) : DELL U2713H
Windows Server 2008 R2 Active Directory Domain Services Primer : Explaining AD DS Replication
Ultrabooks ThinkPad X1 Carbon - Adding Carbon To Your Breakfast
Windows Phone 7 Development : Working with Controls and Themes - Introducing the Metro Design System
Microsoft News – November 2012
Windows Phone 7 Development : Handling Device Exceptions