Programming the Service Bus

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.

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 11-3) and to select a connection payment plan.

Creating a service namespace

Figure 11-3. 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 11-1 shows a few possible addresses.

Example 11-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");

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 11-2.

Example 11-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.

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 11-4.

The service bus registry feed

Figure 11-4. 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();
   }
}

Note

Appendix C uses DiscoverableServiceHost to add discovery-like support for the service bus.

The Service Bus Explorer

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

The Service Bus Explorer

Figure 11-5. 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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.111.33