This sample demonstrates how to use the Windows Azure Service Bus and the NetTcpRelayBinding binding. See the Service Bus documentation for more information about the Service Bus before exploring the samples.
This sample shows a simple service and client that communicate through the Service Bus. When the service application is started, it asks for your issuer credentials and opens an endpoint on the Service Bus. After it is opened, this endpoint has a well-known URI on the Service Bus and is reachable from anywhere, whether or not your computer resides behind a firewall or Network Address Translation (NAT). Clients that access the endpoints must have permission to talk to the endpoint. Therefore, the client application also asks for your issuer credentials, authenticates with the Access Control service, and acquires an access token that proves to the Service Bus infrastructure that the client is authorized to access the endpoint. After the client is connected, you can type messages into the client application, which will be echoed back by the service.
Prerequisites
If you haven't already done so, please read the release notes document that explains how to sign up for a Windows Azure account and how to configure your environment.
Echo Service
The service implements a simple contract with a single operation
named Echo
. The Echo service accepts a string and echoes the string
back.
C# | |
---|---|
[ServiceBehavior(Name = "EchoService", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
class EchoService : IEchoContract
{
public string Echo(string text)
{
Console.WriteLine("Echoing: {0}", text);
return text;
}
} |
The service configuration is shown below:
Xml | |
---|---|
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <!-- Application Service --> <service name="Microsoft.ServiceBus.Samples.EchoService"> <endpoint contract="Microsoft.ServiceBus.Samples.IEchoContract" binding="netTcpRelayBinding" /> </service> </services> </system.serviceModel> </configuration> |
Assuming you have some prior knowledge of the structure of
configuration files for the Windows Communication Foundation (WCF), you will
find that the configuration file is similar to any other WCF configuration file,
with the exception that the configured service endpoint refers to a
NetTcpRelayBinding
binding, which is not part of the .NET
Framework.
The NetTcpRelayBinding binding is one of the bindings introduced with the Service Bus, and the respective configuration element needs to be added to the application configuration file.
The code that hosts the service (in Program.cs or Program.vb) contains two key aspects of interest:
- How does addressing work?
- How do authentication and authorization work?
C# | |
---|---|
Console.Write("Your Service Namespace: "); string serviceNamespace = Console.ReadLine(); Console.Write("Your Issuer Name: "); string issuerName = Console.ReadLine(); Console.Write("Your Issuer Secret: "); string issuerSecret = Console.ReadLine(); // create the service URI based on the service namespace Uri address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService"); // create the credentials object for the endpoint TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior(); sharedSecretServiceBusCredential.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret); // 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.Behaviors.Add(serviceRegistrySettings); endpoint.Behaviors.Add(sharedSecretServiceBusCredential); } // open the service host.Open(); Console.WriteLine("Service address: " + address); Console.WriteLine("Press [Enter] to exit"); Console.ReadLine(); // close the service host.Close(); |
To implement a service that listens to the Service Bus, the Service Bus service must be able to verify that the owner of the listening service is authorized to do so.
Authentication and authorization are both performed by the Access Control service. To make these steps simple, the Microsoft.ServiceBus namespace contains a set of transport client credential helpers that automatically handle the acquisition of the required security tokens.
The credential used in this example is a simple user name/password credential that is backed by the issuer credentials you set up when signing up for a Windows Azure account. To associate a listener endpoint with its Service Bus credentials, you must add a TransportClientEndpointBehavior behavior to the respective endpoint behavior collection. If your service exposes multiple endpoints through the Relay, you can add the same behavior instance to all those endpoints.
Each service namespace automatically owns a branch of the Service Bus global namespace. Your service namespace branch is rooted at:
[scheme]://<service-namespace>.servicebus.windows.net/ |
in which [scheme]
is either sb
(as in this
example) or http
or https
. The namespace owner can
subdivide that namespace and organize services onto that namespace as needed and
define rules in Access Control to guard access to branches of the
namespace.
The preceding code prompts for the issuer credential and then
constructs the listening URI using that information. The static
ServiceBusEnvironment.CreateServiceUri
function is provided to help
construct the URI using the correct format and domain name. It is strongly
recommended that you use this function instead of building the URI from scratch
because the URI construction logic and format might change in future releases.
At present, the resulting listener URI is
scheme://<service-namespace>.servicebus.windows.net/EchoService/
. These
URIs can be used as absolute listening URIs for endpoints, or as the base
address of the service.
Echo Service Client
The client application mirrors the service in terms of its configuration.
Xml | |
---|---|
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <!-- Application Endpoint --> <endpoint name="RelayEndpoint" contract="Microsoft.ServiceBus.Samples.IEchoContract" binding="netTcpRelayBinding"/> </client> </system.serviceModel> </configuration> |
When it runs, the client prompts for the service namespace credentials,
creates a channel to the service, and sends requests by calling the
Echo
operation. After the interaction is complete, the client
closes the channel and exits.
C# | |
---|---|
Console.Write("Your Service Namespace: "); string serviceNamespace = Console.ReadLine(); Console.Write("Your Issuer Name: "); string issuerName = Console.ReadLine(); Console.Write("Your Issuer Secret: "); string issuerSecret = Console.ReadLine(); // create the service URI based on the service namespace Uri address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService"); // create the credentials object for the endpoint TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior(); sharedSecretServiceBusCredential.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret); // create the channel factory loading the configuration ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", new EndpointAddress(serviceUri)); // apply the Service Bus credentials channelFactory.Endpoint.Behaviors.Add(sharedSecretServiceBusCredential); // create and open the client channel IEchoChannel channel = channelFactory.CreateChannel(); channel.Open(); Console.WriteLine("Enter text to echo (or [Enter] to exit):"); string input = Console.ReadLine(); while (input != String.Empty) { try { Console.WriteLine("Server echoed: {0}", channel.Echo(input)); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } input = Console.ReadLine(); } channel.Close(); channelFactory.Close(); |
Running the Sample
To run the sample, build the solution in Visual Studio or from the command line, then run the two resulting executable files. Run the service first, and then run the client. Both programs prompt for your service namespace and the issuer credentials. For the issuer secret, be sure to use the "Default Issuer Key" value from the portal, rather than one of the management keys.
When the service and the client are running, you can start typing messages into the client application. These messages are echoed by the service.
Expected Output - Service
Your Service Namespace: <service-namespace> Your Issuer Name: <issuer-name> Your Issuer Secret: <issuer-secret> Service address: sb://<service-namespace>.servicebus.windows.net/services/EchoService/ Press [Enter] to exit |
Expected Output - Client
Your Service Namespace: <service-namespace>
Your Issuer Name: <issuer-name>
Your Issuer Secret: <issuer-secret>
Enter text to echo (or [Enter] to exit): Hello, World!
Server echoed: Hello, World! |
Did you find this information useful? Please send your suggestions and comments about the documentation.