Hands-On Lab
.NET Services: Introduction to the Service
Bus
Lab version: 2.0.0
Last updated: 11/10/2011
Page 1
CONTENTS
OVERVIEW ................................................................................................................................................... 4
EXERCISE 0: CREATING A SERVICE PROJECT ..................................................................................... 8
Task 1 – Creating your .NET Services Project ........................................................................................ 8
EXERCISE 1: GETTING A BASIC CLIENT AND SERVICE WORKING .................................................. 11
Task 1 – Creating the WCF Service Project and Service Contracts ..................................................... 12
Task 2 – Hosting the WCF Service through the Service Bus................................................................ 18
Task 3 – Configuring the WCF Service................................................................................................. 22
Task 4 – Creating the WCF Client Project............................................................................................ 23
Task 5 – Consuming the WCF Service Hosted through the Service Bus ............................................. 26
Verification 29
EXERCISE 2: BINDINGS, CONNECTION MODES & MEX ENDPOINTS ................................................ 31
Task 1 – Using Hybrid Connection Mode ............................................................................................ 32
Verification 36
Task 2 – Changing the Service Bus Binding ......................................................................................... 38
Verification 41
Task 3 – Exposing a Metadata Endpoint ............................................................................................. 43
Verification 46
EXERCISE 3: MULTICAST MESSAGING THROUGH THE SERVICE BUS ............................................ 50
Task 1 – Building the Internet Relay Chat Application ........................................................................ 51
Task 2 – Chatting through the Service Bus ......................................................................................... 54
Task 3 – Adding Message Protection .................................................................................................. 57
EXERCISE 4: REST-BASED ACCESS AND BINARY DATA .................................................................. 60
Task 1 – Creating the Service Contracts .............................................................................................. 60
Task 2 – Configuring the Service Application ...................................................................................... 62
Verification 63
EXERCISE 5: MESSAGE BUFFER ........................................................................................................... 65
Task 1 – Creating the Order Peek ....................................................................................................... 66
Task 2 – Creating the Order Submitter ............................................................................................... 70
Task 3 – Creating the Order Processor ............................................................................................... 72
Verification 75
Page 2
SUMMARY .................................................................................................................................................. 78
Page 3
Overview
A common problem when developing connected, peer-to-peer applications is to enable connections
with applications through network devices like firewalls and network address translators (NATs).
Network devices like these typically allow applications to initiate outbound network connections but
prevent them from accepting inbound network connections.
To establish a connection through these types of network devices, application developers often end up
writing custom logic that deals with establishing connections across network topologies. Because there
are many different types of network topologies, this logic often becomes very complex.
The Service Bus provides the communication infrastructure that protects developers from having to
create the complex code necessary to achieve seamless connectivity. It allows you to expose a service to
the Internet from behind your firewall or NAT. Several common application messaging patterns are
supported allowing bi-directional, peer-to-peer communication, publish, subscribe and storing and
forwarding of messages.
Facts
The Service Bus is built on Windows Communication Foundation (WCF) and uses standard
Internet protocols.
The Service is cloud-based. The technical aim of the Service Bus is to simplify connectivity
between services and clients, even if those servers and clients exist behind different firewalls
and NAT routers.
Building applications using the Service Bus does not require a significant footprint within an
organization and leads to more rapid deployments while keeping the local infrastructure intact.
As a set of hosted integration technologies, the Service Bus reduces the cost involved in
building, acquiring, and maintaining systems that might have to be built to do the same things.
Objectives
In this Hands-On Lab, you will learn how to:
Expose and consume a service through the Service Bus.
Service Bus bindings options.
Expose a MEX endpoint through the Service Bus.
Implement the Multicast message pattern through the Service Bus.
Use X.509 certificates for message confidentiality.
Expose a REST Service through the Service Bus.
Page 4
Expose binary data through the Service Bus.
Explore the Message Buffer Service Bus capabilities.
Exercises
This Hands-On Lab is composed of the following exercises:
1. Getting a Basic Client and Service Working.
2. Bindings, Connection Modes & MEX Endpoints.
3. Multicast Messaging through the Service Bus.
4. REST-Based Access and Binary Data.
5. MessageBuffer
Starting Materials
This Hands-On Lab includes the following starting materials.
Visual Studio solutions. Depending on the exercise you will find Visual Studio solutions that you
can use as starting point for the exercises.
◦ Ex02-BindingsConnectionModesSample\begin\BindingsConnectionModesSample.sln:
Starting solution for Exercise 2. It consists of a simple application that shows client-
service communication.
◦ Ex03-MulticastSample\begin\MulticastSample.sln: Starting solution for Exercise 3.
◦ Ex04-RESTSample\begin\RESTSample.sln: Starting solution for Exercise 4.
◦ Ex05-MessageBuffer\begin\MessageBuffer.sln: Starting solution for Exercise 5.
Note: Inside each exercise directory, you will find an end folder containing a solution with the
completed lab exercise.
Setup
For convenience, much of the code you will be managing along this hands-on lab is available as Visual
Studio code snippets. The setup needed for this lab consist on checking the prerequisites of this lab and
installing the code snippets. To do this:
1. Run the SetupLab.cmd file located under the lab's Source\Setup folder.
Page 5
2. Follow the instructions to check the dependencies, install any that is missing and install the
code snippets.
Note: To perform the setup steps you may need administrator privileges.
Using the Code Snippets
With code snippets, you have all the code you need at your fingertips. The lab document will tell you
exactly when you can use them. For example,
1. Replace the current interface definition with the following code:
(Code Snippet - Introduction to Service Bus Lab - Ex05 Get Message Buffer)
C#
private static void Main()
{
...
// create the URI for the Message Buffer
Uri messageBufferUri = ServiceBusEnvironment.CreateServiceUri("http",
serviceNamespaceDomain, "OrderMessageBuffer");
Console.WriteLine("Message Buffer address: " +
messageBufferUri.AbsoluteUri);
// Get existing Message Buffer
MessageBufferClient messageBufferClient =
MessageBufferClient.GetMessageBuffer(endpointBehavior, messageBufferUri);
Console.WriteLine("Using existing message buffer");
}
To add this code snippet in Visual Studio you simply place the cursor where you'd like the code
to be inserted, start typing the snippet name, in this case Introduction to Service Bus Lab - Ex05
Get Message Buffer , watch as Intellisense picks up the snippet name, and hit the TAB key twice
once the snippet you want is selected. The code will be inserted at the cursor location.
Page 6
Figure 1
Hit TAB to select the highlighted snippet.
Figure 2
Hit TAB again and the snippet will expand
To insert a code snippet using the mouse rather than the keyboard, right mouse click where you want
the code snippet to be inserted, select Insert Snippet then My Code Snippets and then select the
relevant snippet.
To learn more about Visual Studio IntelliSense Code Snippets, including how to create your own, please
see http://msdn.microsoft.com/en-us/library/ms165392.aspx.
Estimated time to complete this lab: 90 minutes.
Page 7
Exercise 0: Creating a Service Project
To follow this lab and complete all the exercises you first need to create a .NET Services Project. Once
you have created a project, it can be used for all of the .NET Services labs and for your own projects as
well.
Task 1 – Creating your .NET Services Project
In this task, you will create a new .NET Services project.
1. Navigate to https://netservices.azure.com . You will be prompted for your Windows Live ID
credentials if you are not already signed in.
2. Create a new Project. Type a project name, such as your company name or your name, accept
the Terms of Use and click the OK button.
Figure 3
Azure .Net Services – Create a new project
3. Now you will add the first Service Namespace to the project just created. A Service Namespace
represents a namespace for the Service Bus and the Access Control Service. To do this, click in
the Project Name link newly created and then click the Add Service Namespace link.
Page 8
Figure 4
Azure .Net Services – Project Summary
4. Type in a name for your Service Namespace, select a Region for your service to run in, and click
the Create button. Make sure to validate the availability of the name first. Service names must
be globally unique as they are in the cloud and accessible by whomever you decide to grant
access.
Please be patient while your service is activated. It can take a few minutes while it is
provisioned.
You may have to refresh the browser to show the service is active.
Page 9
Figure 5
Azure .Net Services – Creating a Service Namespace
Figure 6
Azure .Net Services – Project Summary listing the Service Namespaces
Note: To sign in at any time, simply navigate to https://netservices.azure.com , click Sign In
and provide your Live ID credentials. Clicking the .Net Services tab on the left will list the
Services Projects associated with your account.
Page 10
Exercise 1: Getting a Basic Client and
Service Working
In this exercise, you will learn how to expose and consume a simple WCF service through the Service
Bus.
The Service Bus simplifies many of the communication challenges by providing a universal naming
convention for services along with a mechanism for direct/indirect communication between two nodes
independent of network topology and configuration.
The Service Bus allows a Windows Communication Foundation-based (WCF) application to listen at a
public network address, even if the application is located behind a NAT or network firewall. This
functionality can be used to help applications communicate with each other, regardless of network
specific structure. Through the use of the Service Bus as an intermediary you can interconnect different
applications securely without the need to write and maintain complex logic and code to traverse
networks.
Another core part of the solution is the Access Control service, a publicly accessible identity and
authentication management service. The .NET Services Access Control Service (ACS) is a service designed
to secure REST web services. ACS allows a REST web services to integrate with both simple clients and
enterprise identity technologies using a single code base. The ACS is also used to secure the Service Bus
endpoints. To accomplish this task, ACS receives an issuer name and an issuer secret (32-bit key), if they
are correctly authenticated, issues a security token (called Simple Web Token) that is then trusted by the
service itself. All messages sent to and via the Service Bus must contain a valid security token.
Page 11
Figure 7
Service Bus message flow
This exercise will expose some Service Bus features like:
Access Control Service authentication methods.
Communication between Client and Service across the Service Bus.
Note: To verify that each step is correctly performed, it is recommended to build the solution at the
end of each task.
Task 1 – Creating the WCF Service Project and Service Contracts
In this task, you will create a WCF Service project that will be then hosted and exposed through the
Service Bus.
1. Open Microsoft Visual Studio 2008 from Start | All Programs | Microsoft Visual Studio 2008 |
Microsoft Visual Studio 2008.
2. On the File menu, point to New, and click Project. In the New Project dialog box, select Visual
C# | Windows. Make sure that .NET Framework 3.5 is selected and choose the Console
Application project type. Set the project name to Service, the solution name to BasicSample
and the location to Ex01-BasicSample\begin in the Source folder of this lab. Click OK to create
the application project.
Page 12
Figure 8
Creating a new project
3. Add a reference to System.ServiceModel.dll assembly. To do this, in Solution Explorer, right-
click the Service project and select Add Reference. In the Add Reference dialog box, select .NET
tab and choose System.ServiceModel assembly. Click OK to add the reference
Note: The Service Bus is built on Windows Communication Foundation.
System.ServiceModel.dll is one of WCF core assemblies.
4. Add references to the Microsoft .Net Services SDK main assembly. To do this, right-click Service
project in Solution Explorer and select Add Reference. In the Add Reference dialog window,
select the Browse tab. Browse to the \ Microsoft .NET Services SDK (Nov 2009
CTP) \Assemblies folder and choose the Microsoft.ServiceBus.dll file. Click OK to add the
reference.
Page 13
Figure 9
Adding a reference to the Service Bus main assemblies
Note: In 64-bit operating systems the Microsoft .NET Services SDK assemblies are located in
the \Microsoft .NET Services SDK (Nov 2009 CTP)\Assemblies folder.
5. Create the WCF service contract. To do this, in Solution Explorer right-click the Service project,
point to Add and select New Item. In the Add New Item dialog box, select Visual C# | Code and
choose the Interface template. Specify a Name value of IEchoContract.cs. Click Add to create
the interface.
Page 14
Figure 10
Creating the IEchoContract interface
6. At the top of the IEchoContract.cs file, add the following namespace directive:
C#
using System.ServiceModel;
7. Make the interface public and apply the ServiceContract attribute to the IEchoContract
interface to indicate that the interface defines a service contract in the WCF application. To do
this, replace the current interface definition with the following code:
(Code Snippet - Introduction to Service Bus Lab - Ex01 Echo Contract)
C#
[ServiceContract(Name = "IEchoContract", Namespace =
"http://samples.microsoft.com/ServiceModel/Relay/")]
public interface IEchoContract
{
}
8. Declare the Echo operation contract to indicate that the method defines an operation that is
part of a service contract. To do this, paste the following code inside the interface definition.
Page 15
(Code Snippet - Introduction to Service Bus Lab - Ex01 Echo Operation Contract)
C#
public interface IEchoContract
{
[OperationContract]
string Echo(string text);
}
9. Create the IEchoChannel interface. To do this, in Solution Explorer right-click the Service
project, point to Add and select New Item. In the Add New Item dialog box, choose the
Interface template. Specify a Name value of IEchoChannel.cs and then click Add.
10. Then make the interface public and make it implement both the IEchoContract interface and
IClientChannel interface as shown below. Notice the System.ServiceModel using namespace
directive.
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace Service
{
public interface IEchoChannel : IEchoContract, IClientChannel
{
}
}
11. Create the EchoService class that will implement the IEchoContract interface. To do this, in
Solution Explorer right-click the Service project, point to Add and select New Item. In the Add
New Item dialog box, choose the Class template. Specify a Name value of EchoService.cs and
then click Add.
Page 16
Figure 11
Creating the EchoService class
12. In EchoService.cs add the following namespace directive:
C#
using System.ServiceModel;
13. Add an inheritance declaration to make the EchoService class implement the IEchoContract
interface and add the public access modifier.
C#
public class EchoService : IEchoContract
14. Add a ServiceBehavior attribute to the EchoService class to indicate that the class will
implement a WCF service. To do this, paste the following code above the class definition.
(Code Snippet - Introduction to Service Bus Lab - Ex01 Echo Service Behavior)
C#
[ServiceBehavior(Name = "EchoService", Namespace =
"http://samples.microsoft.com/ServiceModel/Relay/")]
public class EchoService : IEchoContract
{
}
Page 17
15. Implement the Echo method of the IEchoContract interface. To do this, paste the following
code inside the class definition.
(Code Snippet - Introduction to Service Bus Lab - Ex01 Echo Method)
C#
public class EchoService : IEchoContract
{
public string Echo(string text)
{
Console.WriteLine("Echoing: {0}", text);
return text;
}
}
Task 2 – Hosting the WCF Service through the Service Bus
In this task, you will add code to expose the EchoService service through the Service Bus. The service
will then stay listening for incoming messages at a designed URI.
To communicate across the Service Bus, WCF extensibility points have been used to define a new set of
bindings available to use with the Service Bus. A WCF binding determines what kind of communication
will be exposed or used by a service endpoint. In this lab, you will use a binding named
NetTcpRelayBinding, which is one of the binding introduced with the Service Bus. On the listener side,
the NetTcpRelayBinding enables you to expose an endpoint that will be accessible through a global URI
supported by the Service Bus. When an endpoint using NetTcpRelayBinding has been opened, the URI
will be registered within the Service Bus and from that point, any authorized client will be able to send
messages to that global URI using a similarly configured client. The Service Bus then becomes the
conduit for communication between those two endpoints.
1. Add the following namespace directives to Program class. To do this, in Solution Explorer,
double-click the Program.cs file under the Service project and paste the following code below
the default directives.
C#
using System.ServiceModel;
using System.ServiceModel.Description;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Description;
2. Next, paste the following code inside the Main method. This will prompt the user to provide the
service namespace domain, the issuer name, and the issuer secret.
(Code Snippet – Introduction to Service Bus Lab – Ex01 Main Header)
Page 18
C#
static void Main(string[] args)
{
Console.Title = "Service";
Console.Write("Your Service Namespace Domain (ex.
sb://.servicebus.windows.net/): ");
string serviceNamespaceDomain = Console.ReadLine();
Console.Write("Your Issuer Name: ");
string issuerName = Console.ReadLine();
Console.Write("Your Issuer Secret: ");
string issuerSecret = Console.ReadLine();
}
3. Create the URI for the service based on the service namespace, this is the address where the
service will be hosted. To do this, add the following code (shown in bold):
(Code Snippet - Introduction to Service Bus Lab - Ex01 Create Uri)
C#
static void Main(string[] args)
{
// ...
// create the service URI based on the service namespace
Uri address = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespaceDomain, "EchoService");
}
Note: The URI points out to the address where the service will be hosted. The generated URI
will have the following format: sb://.servicebus.windows.net/EchoService/
Notice that to create the URI, you are passing "sb" as the scheme, followed by the Service
Namespace identity. “EchoService” is being used as part of the URI to host the service.
4. Create a TransportCliendEndpointBehavior to specify which type of credentials should be used
to authenticate the service with the Service Bus. Specify a CredentialType of type SharedSecret,
which relies on the issuer name and issuer secret key obtained when signing up for
Microsoft .NET Services in the exercise 0.
(Code Snippet - Introduction to Service Bus Lab - Ex01 Create Credential object for the Endpoint)
C#
static void Main(string[] args)
{
Page 19
// ...
// create the service URI based on the service namespace
Uri address = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespaceDomain, "EchoService");
// create the credential object for the endpoint
TransportClientEndpointBehavior sharedSecretServiceBusCredential = new
TransportClientEndpointBehavior();
sharedSecretServiceBusCredential.CredentialType =
TransportClientCredentialType.SharedSecret;
sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerName =
issuerName;
sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerSecret =
issuerSecret;
}
Note: Authentication and authorization are both performed by the .NET Services 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 transportClientEndpointBehavior allows you to specify the
Credential Type to be used to authenticate the service. In this case, you are using
SharedSecret, which relies on the issuer name and issuer key to be used to authenticate with
the Service Bus.
As well as SharedSecret, there are other credential types;
- SimpleWebToken: The client authenticates with the Service Bus using a SimpleWebToken
credential (the SharedSecretCredential.ComputeSimpleWebTokenString(string issuerName,
string issuerSecret) method compute the string that is expected by
TransportClientEndpointBehavior).
- Unauthenticated: No client credential provided. In the service configuration file, the
relayClientAuthenticationType setting controls whether or not a client is required to
authenticate when accessing the HTTP service. Setting this to “None” means that access is
granted to anyone consuming the service. A typical scenario for unauthenticated services is
exposing RSS feeds.
5. Create a ServiceHost object to host the EchoService as a WCF Service. Paste the following code
below the one inserted previously:
(Code Snippet - Introduction to Service Bus Lab - Ex01 Create Service Host)
C#
static void Main(string[] args)
Page 20
{
// ...
// create the service host reading the configuration
ServiceHost host = new ServiceHost(typeof(EchoService), address);
}
6. 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. Paste the following code below the one inserted previously in
order to add the behavior for all endpoints:
(Code Snippet - Introduction to Service Bus Lab - Ex01 Add Service Bus Credentials to Endpoints)
C#
static void Main(string[] args)
{
// ...
// 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);
}
}
7. Add the code to open the host and leave it listening at the Relay Service until the user press any
key. To do this, add the following code to Main method.
(Code Snippet - Introduction to Service Bus Lab - Ex01 Open Service Host)
C#
static void Main(string[] args)
{
// ...
// open the service
Page 21
host.Open();
Console.WriteLine("Service address: " + address);
Console.WriteLine("Press [Enter] to exit");
Console.ReadLine();
// close the service
host.Close();
}
Note: When you call ServiceHost.Open, the NetTcpRelayBinding causes WCF to communicate
with the Service Bus in order to authenticate the service identity and to authorize it to listen
on the specified URI.
Task 3 – Configuring the WCF Service
In this task, you will create the configuration file (App.config) for the WCF Service.
1. Add an Application Configuration File to the Service project. To do this, right-click Service
project, point to Add and select New Item. In the Add New Item dialog box, select the
Application Configuration File template, leave the name by default and click Add.
Figure 12
Creating a configuration file for the service
Page 22
2. Add a services configuration section including a service tag for the EchoService. To do this, add
the following code to App.Config.
XML
3. Add an endpoint definition for the service. To do this, add the following code (shown in bold)
inside the service configuration.
XML
Note: The endpoints are configured to use a binding of type netTcpRelayBinding.
Task 4 – Creating the WCF Client Project
In this task, you will create the project for the client WCF application and define the proxy to
communicate with the service.
1. Create the Client project. To do this, in Solution Explorer, right-click BasicSample solution,
point to Add and select New Project. In the New Project dialog box, select the Console
Application project type. Set the project name to Client, and click OK.
Page 23
Figure 13
Creating the client project
2. Add a reference to ServiceModel assembly. To do this, in Solution Explorer, right-click the
Client project and select Add Reference. In the Add Reference dialog box, in the .NET tab,
select System.ServiceModel assembly. Click OK to add the reference
3. Add references to Microsoft .Net Services SDK core assembly. To do this, right-click Client
project in Solution Explorer and select Add Reference. In the Add Reference dialog window,
select the Browse tab. Browse to \ Microsoft .NET Services SDK (Nov 2009
CTP)\Assemblies and select the Microsoft.ServiceBus.dll file. Click OK to add the reference.
Note: In 64-bit operating systems the Microsoft .NET Services SDK assemblies are located in
the \Microsoft .NET Services SDK (Nov 2009 CTP)\Assemblies folder.
4. Create the Echo client proxy. To do this, in Solution Explorer right-click the Client project, point
to Add and select New Item. In the Add New Item dialog box, select Visual C# | Code and
choose the Interface template. Specify a Name value of EchoProxy.cs. Click Add to create the
Interface.
Page 24
Figure 14
Creating the EchoProxy interface
5. In EchoProxy.cs, add the following namespace directive:
C#
using System.ServiceModel;
6. Define the interface. To do this, replace the current interface definition (EchoProxy) with the
following code (shown in bold):
(Code Snippet - Introduction to Service Bus Lab - Ex01 Echo Proxy Contract)
C#
[ServiceContract(Name = "EchoContract", Namespace =
"http://samples.microsoft.com/ServiceModel/Relay/")]
public interface IEchoContract
{
}
7. Define the Echo operation contract. To do this, paste the following code inside IEchoContract
class:
C#
[ServiceContract(Name = "EchoContract", Namespace =
"http://samples.microsoft.com/ServiceModel/Relay/")]
Page 25
public interface IEchoContract
{
[OperationContract]
string Echo(string text);
}
8. Declare the channel to communicate with the service. To do this, paste the following code
below the IEchoContract interface definition:
C#
public interface IEchoContract
{
...
}
public interface IEchoChannel : IEchoContract, IClientChannel { }
Task 5 – Consuming the WCF Service Hosted through the Service Bus
In this task, you will create the service proxy and connect to the hosted service.
1. Add the following namespace directives to Program class. To do this, in Solution Explorer,
double-click Program.cs under Client project and paste the following code below the default
namespace directives:
C#
using System.ServiceModel;
using Microsoft.ServiceBus;
2. Add code to let you type the service namespace, the credentials, and then create a channel to
the service. The authentication type used is SharedSecret, the same configuration that was
done in the step 4 of task 2. To do this, paste the following code inside Main method.
(Code Snippet - Introduction to Service Bus Lab - Ex01 Client)
C#
static void Main(string[] args)
{
Console.Title = "Client";
Console.Write("Your Service Namespace Domain (ex.
sb://.servicebus.windows.net/): ");
string serviceNamespaceDomain = Console.ReadLine();
Console.Write("Your Issuer Name: ");
string issuerName = Console.ReadLine();
Console.Write("Your Issuer Secret: ");
Page 26
string issuerSecret = Console.ReadLine();
// create the service URI based on the service namespace
Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespaceDomain, "EchoService");
// create the credentials object for the endpoint
TransportClientEndpointBehavior sharedSecretServiceBusCredential =
new TransportClientEndpointBehavior();
sharedSecretServiceBusCredential.CredentialType =
TransportClientCredentialType.SharedSecret;
sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerName =
issuerName;
sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerSecret
= issuerSecret;
// create the channel factory loading the configuration
ChannelFactory channelFactory = new
ChannelFactory("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();
}
3. Add the code to request the user to enter a message to be sent to the service and then proceed
to send it (by calling EchoChannel.Echo). If the user enters an empty string the application ends.
(Code Snippet - Introduction to Service Bus Lab - Ex01 Client User Interaction)
C#
static void Main(string[] args)
{
...
channel.Open();
Console.WriteLine("Enter text to echo (or [Enter] to exit):");
string input = Console.ReadLine();
while (input != String.Empty)
{
Page 27
try
{
Console.WriteLine("Server echoed: {0}", channel.Echo(input));
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
input = Console.ReadLine();
}
}
Note: When the Relay Service receives an incoming message from an authorized sender
(Client), it simply relays the message to an instance of the EchoService running locally.
EchoService creates an application response and sends it back to the Relay Service.
The Relay Service completes the message flow by sending the response to the client
containing the EchoService response message.
4. Add the code to close both the Channel and the ChannelFactory.
(Code Snippet - Introduction to Service Bus Lab - Ex01 Close Channel)
C#
static void Main(string[] args)
{
while (input != String.Empty)
{
...
}
channel.Close();
channelFactory.Close();
}
5. Add an Application Configuration File to the Client project. To do this, right-click Client project,
point to Add and select New Item. In the Add New Item dialog box select the Application
Configuration File template, leave the name by default and click Add.
6. Add an endpoint and binding configuration for the proxy used in the client side. To do this,
paste the following code in App.config:
Page 28
C#
Verification
In order to verify that you have correctly performed every step of exercise one, proceed as follows.
1. You will need to create a Project and a Service Namespace. If you have not already done so,
please go to Exercise 0.
2. Run the Service. To do this, right-click Service project, point to Debug and select Start New
Instance.
3. Enter the Service Namespace Domain; this is the Service Namespace you have entered when
provisioning an account at the portal Web Site. After that, enter the Issuer Name and Issuer
Secret; these are the name and key generated by the service namespace at the portal Web Site.
Figure 15
Entering the Service Namespace, Issuer Name, and Issuer Secret
Page 29
4. Run the WCF Client. To do this, in Visual Studio, right-click the Client project, point to Debug
and select Start New Instance.
5. Enter the Service Namespace Domain; this is the Service Namespace you have entered when
provisioning an account at the portal Web Site. After that, enter the Issuer Name and Issuer
Secret; these are the name and key generated by the service namespace at the portal Web Site.
Figure 16
Entering the Service Namespace, Issuer Name and Issuer Secret
Note: In this hands-on-lab, both the client and the service use the same credentials; therefore,
no additional steps are required to grant the client access to listen or to send a message to the
service through the Service Bus. By default, a credential is granted with Listen, Send, and
Manage privileges within its own Service Bus service namespace. If the client is using a
different credential than the service, a specific Access Control rule is needed for a client
credential to gain Listen, Send or Manage privileges in the Service Bus service namespace for
the service.
6. Type some messages in the Client console. Messages will be sent to the Service via the Service
Bus.
Page 30
Figure 17
Messages sent to the hosted service
7. The Service receives the messages via the Relay Service and outputs them.
Figure 18
Service receives and outputs the messages
Exercise 2: Bindings, Connection Modes
& MEX Endpoints
Page 31
In this exercise you will modify a simple application that demonstrates service-client communication
(similar to the one you have built in the previous exercise) to try different connection modes and
bindings that can be used to communicate sender and receivers across the Service Bus.
The Service Bus allows the usage of numerous bindings and connection modes between senders and
receivers that determine how the connection to the Service Bus is made. The different bindings and
connection modes offer a great deal of flexibility for specific communication scenarios.
The following table describe the most significant connection modes that will be shown during this
exercise:
Connection Mode Description
Configures the binding to use the relay to exchange
Relayed messages between the client and the service. This is
the default connection mode.
Hybrid connection capabilities - After establishing a
relayed connection, it switches automatically to a direct,
non-relayed connection whenever possible. A direct
Hybrid connection mode between the client and the service is
an optimization of the Relayed mode because it attempts
to bridge a direct connection between the sender and
receiver, if possible.
In addition, you will learn how to expose a metadata endpoint through the Service Bus.
This exercise will expose some Service Bus features like:
Service Bus Connection Modes: Hybrid and Relayed.
Service Bus Bindings
Exposing Metadata Exchange (MEX) Endpoints through the Service Bus.
Note: To verify that each step is correctly performed, it is recommended to build the solution at the
end of each task.
Task 1 – Using Hybrid Connection Mode
In this task, you will change the connection mode to Hybrid.
1. Open Microsoft Visual Studio 2008 from Start | All Programs | Microsoft Visual Studio 2008 |
Microsoft Visual Studio 2008.
2. Open the solution file located by default Ex02-
BindingsConnectionModesSample\begin\BindingsConnectionModesSample.sln in the Source
folder of this lab. Alternatively, you may continue working with the solution obtained after
completing the previous exercise.
Page 32
3. Open the App.config file under the Client project. Add a section for the WCF bindings inside the
system.serviceModel section and include an override for the netTcpRelayBinding binding. This
is the plumbing for adding a custom binding configuration, overriding the default behavior of
the netTcpRelayBindig. To do this, add the following code.
XML
...
4. Change the Client connection mode to Hybrid. To do this, add a connectionMode attribute to
the binding configuration, set the security mode to None and add the bindingConfiguration
attribute to the endpoint as shown in the following code:
XML
Page 33
Note: One important property on the NetTcpRelayBinding object is ConnectionMode. The
property type is an enum named Microsoft.ServiceBus.TcpRelayConnectionMode and
describes the type of connection to be established between clients and services.
The connection mode is being set to Hybrid, which first establishes a relayed connection, and
if possible, switches automatically to a direct connection between a client and service.
Figure 19
Relayed Connection Mode
5. Open the App.config file under the Service project and add the bindings and
netTcpRelayBinding section as shown in the following code:
XML
Page 34
...
6. Next, change the Service connection mode to Hybrid. To do this, in the App.config file of the
Service project add a connectionMode attribute to the binding configuration as shown below:
XML
7. Set the bindingConfiguration attribute in the service endpoint to the binding configuration just
created as shown below:
XML
...
8. Display a notification when the connection is switched to Hybrid after the communication has
been established. To do this, add the following code to the Program class of the Client project
after the channel has been opened.
(Code Snippet - Introduction to Service Bus Lab - Ex02 Connection Change Notification)
Page 35
C#
channel.Open();
IHybridConnectionStatus hybridConnectionStatus =
channel.GetProperty();
if (hybridConnectionStatus != null)
{
hybridConnectionStatus.ConnectionStateChanged += (o, e) =>
{
Console.WriteLine("Connection state changed to: {0}.",
e.ConnectionState);
};
}
Console.WriteLine("Enter text to echo (or [Enter] to exit):");
Verification
1. Run the Service. To do this, right-click Service project, point to Debug and select Start New
Instance. Enter the Service Namespace Domain; this is the Service Namespace you have
entered when provisioning an account at the portal Web Site. After that, enter the Issuer Name
and Issuer Secret; these are the name and key generated by the service namespace at the
portal Web Site.
Figure 20
Service running through the Service Bus
Page 36
2. Run the Client. To do this, in Visual Studio, right-click the Client project, point to Debug and
select Start New Instance. Enter the Service Namespace Domain; and then the Issuer Name
and Issuer Secret.
Figure 21
Client running and connection mode changed to Direct mode.
Note: When running the Client, the firewall may popup a message here. If this happens, click
Allow Access.
3. Send several messages to ensure the messages are correctly echoed by the service.
Figure 22
Page 37
Service receives and outputs the messages
Note: When a direct connection between the sender and receiver is established, the messages
do not need to be relayed through the Service Bus.
Figure 23
Direct Connection Mode
4. Close both the Client and the Service.
Task 2 – Changing the Service Bus Binding
In this task, you will learn how to change the transport protocol by using the different bindings provided
by the Service Bus.
1. Change the binding used in the Service from netTcpRelayBinding to ws2007HttpRelayBinding.
To do this, open App.config under the Service project and replace the section with
the following code.
XML
...
Page 38
...
2. Change the binding specified in the service endpoint from netTcpRelayBinding to
ws2007HttpRelayBinding. To do this, replace the binding attribute for the tag with
the following code (highlighted in bold).
XML
3. Change the URI address at where the service will be hosted to map the new binding. To do this,
open Program.cs under the Service project and replace the scheme used for creating the URI
from sb to http as show in the following code (shown in bold) in the Main method.
C#
…
string issuerSecret = Console.ReadLine();
// create the service URI based on the service namespace
Uri address = ServiceBusEnvironment.CreateServiceUri("http",
serviceNamespaceDomain, "EchoService");
…
Page 39
4. Now you will change the binding for the Client project. To do this, open App.config under the
Client project and replace the section with the following code.
XML
...
5. Change the binding specified in the client endpoint from netTcpRelayBinding to
ws2007HttpRelayBinding. To do this, replace the binding attribute for the tag with
the following code (highlighted in bold).
XML
...
6. Change the URI address at where the service is located to map the new binding. To do this,
open Program.cs under the Client project and replace the scheme used for creating the URI
from sb to http as show in the following code (shown in bold) in the Main method.
C#
string issuerSecret = Console.ReadLine();
Page 40
// create the service URI based on the service namespace
Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("http",
serviceNamespaceDomain, "EchoService");
Verification
1. Run the Service. To do this, right-click Service project, point to Debug and select Start New
Instance. You will have to provide the service namespace under which the Service is hosted.
This is the Service Namespace you have entered when provisioning an account at the portal
Web Site. After that, enter the Issuer Name and Issuer Secret; these are the name and key
generated by the service namespace at the portal Web Site.
Figure 24
Service running though the Service Bus with ws2007HttpRelayBinding
Note: Http services require administrative privileges in order to register Url. For instance, if
you see the following error message:
Page 41
It means that the namespace where the service is being hosted hasn't been reserved yet. To
solve this, the following command must be run with administrative privileges:
netsh http add urlacl url=http://+:80/EchoService/ user=DOMAIN\user
Where DOMAIN\user is the user that will run the Service console application.
Notice that you could also workaround this by launching Visual Studio as an administrator.
2. Run the Client. To do this, in Visual Studio, right-click the Client project, point to Debug and
select Start New Instance. Enter the Service Namespace Domain; and then the Issuer Name
and Issuer Secret.
Figure 25
Client running with ws2007HttpRelayBinding
Page 42
3. Send several messages to ensure the messages are correctly echoed by the service.
Figure 26
Service receives and outputs the messages
Task 3 – Exposing a Metadata Endpoint
In this task, you will learn how to expose a metadata endpoint through the Service Bus.
1. Add the metadata endpoint definition to the service configuration. To do this, open App.config
under the Service project and add the following endpoint node inside tag.
XML
Page 43
2. To add Metadata publishing to the Service, modify the application configuration to include the
service behavior section. To do this, add the following tag below the
one as shown below:
XML
...
3. Set the metadata behavior to the service. To do this, add the following behaviorConfiguration
property to the service definition:
XML
...
4. Set back the service binding to netTcpRelayBinding. To do this, open App.config under the
Service project and replace the existing binding in the section with the following
code.
XML
...
Page 44
...
5. Set back the binding specified in the service endpoint to netTcpRelayBinding. To do this,
replace the binding attribute for the tag with the following code (highlighted in
bold).
XML
...
...
...
6. Change the URI address at where the service will be hosted to map the new binding. To do this,
open Program.cs under the Service project and replace the scheme used for creating the URI
from http to sb as show in the following code (shown in bold) in the Main method.
C#
...
string issuerSecret = Console.ReadLine();
// create the service URI based on the service namespace
Uri address = ServiceBusEnvironment.CreateServiceUri("sb",
serviceNamespaceDomain, "EchoService");
// create the service host reading the configuration
Page 45
ServiceHost host = new ServiceHost(typeof(EchoService), address);
...
7. Add the following namespace directive to Program class. To do this, in Solution Explorer,
double-click Program.cs under Service project and paste the following code below the default
directives.
C#
using System.ServiceModel.Dispatcher;
8. Add the code to display at which addresses the service is listening at. To do this, open
Program.cs under the Service project and paste the following code (shown in bold) in the Main
method.
(Code Snippet - Introduction to Service Bus Lab - Ex02 Display Addresses)
C#
...
host.Open();
foreach (ChannelDispatcherBase channelDispatcherBase in
host.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as
ChannelDispatcher;
foreach (EndpointDispatcher endpointDispatcher in
channelDispatcher.Endpoints)
{
Console.WriteLine("Listening at: {0}",
endpointDispatcher.EndpointAddress);
}
}
Console.WriteLine("Service address: " + address);
...
Verification
In order to verify that the Service is exposing Metadata proceed as follows. You will use the
ServiceModel Metadata Utility (svcutil) to download metadata documents from the Service.
Note: Svcutil.exe is installed as part of the Windows SDK. A typical location might be
C:\Program Files\Microsoft SDKs\Windows\\Bin\SvcUtil.exe
Page 46
1. Run the Service. To do this, right-click the Service project, point to Debug and select Start New
Instance. You will have to provide the service namespace under which the Service is hosted.
This is the Service Namespace you have entered when provisioning an account at the portal
Web Site. After that, enter the Issuer Name and Issuer Secret; these are the name and key
generated by the service namespace at the portal Web Site.
Figure 27
Service running showing also the mex endpoint
2. In order to download the metadata from the running service, this requires settings in
SvcUtil.exe.config file to authenticate the client. To do this, navigate to
%ProgramFiles%\Microsoft SDKs\Windows\\Bin\ open the SvcUtil.exe.config file,
paste the following settings inside the configuration section and replace the ISSUER_NAME and
ISSUER_SECRET placeholder strings with your issuer name and secret of your service
namespace.
XML
3. Execute the Svcutil tool to download the metadata from the running service. To do this, open a
Visual Studio Command Prompt as an administrator from Start | All Programs | Microsoft
Visual Studio 2008 | Microsoft Visual Studio Tools | Visual Studio 2008 Command Prompt,
navigate to the folder where you want to generate the files (using CD command), the folder
containing this Lab Source recommended, and run the following command. Make sure to run
the command prompt with administrative privileges.
Note: Please replace [serviceNamespace] with your current service namespace, which you
created in the exercise 0.
Command
svcutil.exe sb://[serviceNamespace].servicebus.windows.net/EchoService/mex
4. EchoService.cs files and Output.config files will be created.
Page 48
Figure 28
Running the Svcutil tool
5. The output.config file generated should be similar to the following:
XML
Page 49
Exercise 3: Multicast Messaging through
the Service Bus
In this exercise, you will build a simple internet relay chat application that demonstrates multicast
messaging through the Service Bus. Multicast, otherwise known as simple publish/subscribe, enables
multiple listeners and senders at a single URI. Every actor is both a listener and sender at the same time.
To implement multicast messaging pattern, the Service Bus provides another binding called
netEventRelayBinding. This binding enables a publish/subscribe communication pattern over WCF,
which is not available from any of the built-in WCF bindings. The netEventRelayBinding binding allows
multiple applications to subscribe to messages sent to an endpoint. Any messages sent to that endpoint
are received by all applications.
The Service Bus implements the netEventRelayBinding by allowing multiple listeners to register
themselves at a URI specified by the first sender. Each service host that has an endpoint listening on that
same URI implicitly becomes a subscriber. When a client sends a message to that URI, the message is
delivered to all service endpoints currently subscribed. In this scenario, the back-end system plays the
role of the WCF client and broadcasts (publishes) a message to all subscribers.
Page 50
Figure 29
Multicasting using the netEventRelayBinding
You will learn how to provide message protection by using X.509 certificates.
This exercise will expose some Service Bus features like:
Service Bus netEventRelayBinding.
Using X.509 Certificates for Message Confidentiality.
Note: This exercise could be executed with a single solution, by opening two instances. However, it’s
interesting to run it using two different machines and two different Microsoft .NET Services accounts.
Also, enabling tracing and message logging allows you to understand how the relay works.
Task 1 – Building the Internet Relay Chat Application
In this task, you will build the chat application based on a provided Visual Studio solution.
To be able to chat between two different applications you need to have two different user accounts.
1. Open Microsoft Visual Studio 2008 from Start | All Programs | Microsoft Visual Studio 2008 |
Microsoft Visual Studio 2008.
2. Open the MulticastSample.sln solution file from Ex03-MulticastSample\begin\ in the Source
folder of the lab.
Page 51
3. Configure the service and the client binding. To do this, in the Solution Explorer, double-click
App.config and paste the following code (shown in bold) inside the tag.
XML
4. Change the binding specified in both the client and service endpoint from netTcpRelayBinding
to netEventRelayBinding. To do this, open the App.config and replace the binding attribute for
both tags with the following code (highlighted in bold).
XML
...
5. Define service contract operations. To do this, in the Solution Explorer, double-click
IMulticastContract.cs to open the service contract and paste the following code inside the
interface definition. Hello and Bye methods are used within the application to notify
participants when a user joins and leaves the chat. Chat method is called by the application
when a user provides a string to contribute to the conversation.
(Code Snippet - Introduction to Service Bus Lab - Ex03 Multicast Contract Operations)
C#
Page 52
public interface IMulticastContract
{
[OperationContract(IsOneWay = true)]
void Hello(string nickname);
[OperationContract(IsOneWay = true)]
void Chat(string nickname, string text);
[OperationContract(IsOneWay = true)]
void Bye(string nickname);
}
Note: The netEventRelayBinding requires contracts to expose one way operations only.
Therefore all operations must be marked with “IsOneWay=true” to indicate that the operation
only consists of a single input message and has no associated output message.
6. Implement service operations. To do this, in the Solution Explorer double-click
MulticastService.cs to open the service implementation. Paste the following code inside
MulticastService class:
(Code Snippet - Introduction to Service Bus Lab - Ex03 Multicast Service Operations)
C#
public class MulticastService : IMulticastContract
{
void IMulticastContract.Hello(string nickname)
{
Console.WriteLine("[" + nickname + "] joins");
}
void IMulticastContract.Chat(string nickname, string text)
{
Console.WriteLine("[" + nickname + "] says: " + text);
}
void IMulticastContract.Bye(string nickname)
{
Console.WriteLine("[" + nickname + "] leaves");
}
}
7. Implement the chat behavior. To do this, open Program.cs and paste the following code (shown
in bold).
Page 53
(Code Snippet - Introduction to Service Bus Lab - Ex03 Chat behavior)
C#
public static void Main()
{
...
Console.WriteLine("Press [Enter] to exit");
Console.WriteLine();
channel.Hello(nickname);
string input = Console.ReadLine();
while (!string.IsNullOrEmpty(input))
{
channel.Chat(nickname, input);
input = Console.ReadLine();
}
channel.Bye(nickname);
channel.Close();
channelFactory.Close();
host.Close();
}
Note: The Hello method will notify all participating applications of the arrival of a new user. All
strings are sent as messages to all participating applications until an empty string is provided
as input (MulticastChannel.Chat). Finally, the Bye method notifies all participants of the
departure of the client.
Task 2 – Chatting through the Service Bus
In this task you will run two instances of the chat application and exchange messages between them by
using the Service Bus multicast features.
1. Run one instance of the chat application. To do this, right-click the MulticastSample project,
point to Debug and select Start New Instance.
2. Enter the name of the chat session and press Enter (you might use “ServiceBusChatSession”).
You will have to provide the service namespace under which the Service is hosted. This is the
Service Namespace you have entered when provisioning an account at the portal Web Site.
After that, enter the Issuer Name and Issuer Secret. Then enter the nickname you want to use
during the chat session.
Page 54
Figure 30
Entering the chat session
3. Run another instance of the chat application. To do this, in Visual Studio, right-click
MulticastSample project, point to Debug and select Start New Instance.
4. In this new instance, enter the same name of the chat session you have entered before
(“ServiceBusChatSession”). You will have to provide the service namespace domain under which
the Service is hosted and the Issuer Name and Key. Then type nickname you want to use during
the chat session (different from the previous one).
Figure 31
Page 55
Joining both applications to the chat session
Note: One endpoint hosted at the Service Bus Relay is shared by all the client applications
wishing to exchange messages. All client applications will be subscribers to messages sent to
the URI:
“sb://[yourServiceNamespace].servicebus.windows.net/[chatSessionName]/MulticastService/”
. This sounds awkward since any solution hosted at the Service Bus might be able to listen and
send events to that endpoint by knowing the URL only. The next task shows how to mitigate
that by protecting messages using X509 certificates.
5. Try sending messages from both applications and verify both participants receive messages.
Figure 32
Chatting using the MultiCast Service
Note: Each message is sent to the Service Bus, which then relays the messages to all the
services currently subscribed to the same URI.
6. Press Enter in one of the consoles to end one chat application.
Page 56
Figure 33
Leaving the chat session
Note: Notice that the other application receives the notification of the participant leaving the
chat session.
7. Press Enter in the other chat application console to end it.
Task 3 – Adding Message Protection
In this task, you will learn how to protect the messages that are sent by the participants by using X.509
certificates to encrypt the messages.
1. Open a Visual Studio 2008 Command Prompt as administrator and navigate to the folder Assets
located inside the Source folder provided with the lab.
2. Execute the command file SetupCertificates.cmd as shown below. Notice that you must provide
as parameter, the Service Namespace, this is the same service namespace, which you have
created during the provisioning process at the web site portal. This command file installs the
certificates required to encrypt the messages.
Visual Studio 2008 Command Prompt
SetupCertificates.cmd YOUR_SERVICE_NAMESPACE
3. Add new behaviors in the configuration file to specify credentials for the service and the client.
To do this, open App.config and replace the section with the following code
(shown in bold) under tag (make sure to replace the whole section).
Finally, in the ServiceCertificate and DefaultCertificate elements replace the findValue
Page 57
attribute with the Service Namespace (Highlighted in bold). Make sure that correspond with
the service namespace that you have created during the provisioning process account and with
the certificate you newly created in the preview step.
XML
...
Page 58
Note: The clientCredentials behaviors define a service certificate. A service certificate is used
by a client to authenticate the service and provide message protection. This configuration
references a "[YOUR_SERVICE_NAMESPACE].servicebus.windows.net" X.509 certificate
installed in this task.
4. Replace current service configuration with the following code (highlighted in bold).
XML
5. Add a behaviorConfiguration attribute to the client’s endpoint configuration to specify the
behavior for the client. To do this, add the following code to client’s endpoint section:
XML
6. Configure the security of the netEventRelayBinding to use message security and certificate
credentials. To do this, replace the current bindings section in the configuration with the
following:
XML
Page 59
Note: You can now follow the steps in Task 2 to verify the chat application continues working
as expected. If you configure tracing and message logging you will realize that transport level
traces shows encrypted payloads.
Exercise 4: REST-Based Access and
Binary Data
In this exercise, you will learn how to expose a REST Service through the Service Bus. This service, when
accessed through a web browser, will expose binary data through a URL with the following pattern:
http://[ServiceNamespace].servicebus.windows.net/Image/.
Notice the protocol being used differs from the one used in the previous exercises. We are still accessing
the service through the Service Bus but we are using the webHttpRelayBinding instead of the default
netTcpRelayBinding used in the previous exercises.
This exercise will expose some Service Bus features like:
REST-Based Access to services.
Exposing Binary Data through the Service Bus.
Note: To verify that each step is correctly performed, it is recommended to build the solution at the
end of each task.
Task 1 – Creating the Service Contracts
1. Open Microsoft Visual Studio 2008 from Start | All Programs | Microsoft Visual Studio 2008 |
Microsoft Visual Studio 2008.
2. Open the RestSample.sln solution file from Ex04-RESTSample\begin\ in the Source folder of
the lab.
3. Define IImageContract operations. To do this, in Solution Explorer, double-click
IImageContract.cs and paste the following code (shown in bold) inside IImageContract
interface.
(Code Snippet - Introduction to Service Bus Lab - Ex04 GetImage Operation Contract)
Page 60
C#
public interface IImageContract
{
[OperationContract(Action = "GET", ReplyAction = "GETRESPONSE")]
Message GetImage();
}
Note: GetImage method is adorned with an OperationContract attribute with an Action
(“GET”) and a ReplyAction (“GETRESPONSE”) so that incoming HTTP get requests will be
routed to this operation, and the operation is responsible for sending the responses as well.
4. Implement ImageService’s GetImage operation. To do this, open ImageService.cs and add the
following code to the ImageService class.
(Code Snippet - Introduction to Service Bus Lab - Ex04 GetImage Implementation)
C#
public class ImageService : IImageContract
{
...
public Message GetImage()
{
Message response =
StreamMessageHelper.CreateMessage(OperationContext.Current.IncomingMessageVers
ion, "GETRESPONSE", this.WriteImage);
HttpResponseMessageProperty responseProperty = new
HttpResponseMessageProperty();
responseProperty.Headers.Add("Content-Type", "image/jpeg");
response.Properties.Add(HttpResponseMessageProperty.Name,
responseProperty);
return response;
}
}
Note: When GetImage is called, the response returns a message containing the image, which
is read from a file included in the solution.
The message is created using StreamMessageHelper class. This class, provided by the Service
Bus SDK, is used to send and receive non-XML streams within the body of a message. It is
particularly useful for receiving and sending streams to HTTP clients through the Service Bus
StreamMessageHelper.CreateMessage method is used to create a Message object with a
delegate callback. When the message is serialized, the delegate is called with a Stream object
Page 61
which can be used to write the body of the message. In this case, WriteImage creates and
returns an in-memory version of the image.
Another overload of CreateMessage takes a stream, which can return the image from disk. In
this case, the stream should use a “read-only open” of the file to prevent access violations
when multiple clients access the service.
Task 2 – Configuring the Service Application
In this task, you will create the configuration file (App.config) for the Service.
1. Configure the service binding to use WebHttpRelayBinding. This binding allows exposing a
service to be accessed through HTTP. To do this, open App.config and paste the following code
(shown in bold) in the section.
XML
2. Configure the service and its endpoints. To do this, paste the following code inside the
section.
XML
Page 62
3. Set Issuer Name and Issuer Secret attribute in the sharedSecret section. These are the issuer
name and issuer secret of your Service Namespace Domain, which you have entered when
provisioning an account at the portal Web Site.
XML
...
...
4. Specify the URI through which the service will be exposed. To do this, open Program.cs and
paste this code as shown below, make sure to delete the provided dummy URI:
(Code Snippet - Introduction to Service Bus Lab - Ex04 Service URI)
C#
private static void Main()
{
Console.Write("Your Service Namespace Domain (ex.
https://.servicebus.windows.net/): ");
string serviceNamespaceDomain = Console.ReadLine();
Uri address = ServiceBusEnvironment.CreateServiceUri("https",
serviceNamespaceDomain, "Image");
ServiceHost host = new ServiceHost(typeof(ImageService), address);
host.Open();
...
}
Note: The service will be listening at:
https://[ServiceNamespace].servicebus.windows.net/Image/
Verification
In order to verify that you have correctly performed every step of exercise four, proceed as follows.
1. Run the Service. To do this, right-click the Service project, point to Debug and select Start New
Instance. When prompted, provide the service namespace you have set up during the
Page 63
provisioning process. At this point, the service should indicate that it is listening at the
configured address.
Figure 34
REST service running
2. Access the service Uri within a Web Browser. To do this, open a Web Browser and navigate to
the URL provided in the service console
(https://[ServiceNamespace].servicebus.windows.net/Image/). Observe the returned image:
Page 64
Figure 35
Accessing the REST service
Note: The web browser is acting as the client.
3. Close the browser and press Enter in the service’s console to end this verification.
Exercise 5: Message Buffer
In this exercise you will learn how Message Buffer work in .NET Services and how to use them.
This exercise is based on an order-processing scenario. It consists of three small applications: the order
submitter, the order processor, and the order peeker. The submitter will send the orders as typed
messages to a .NET Services Message Buffer; these orders, will be read from the .NET Services Message
Buffer and processed by one or more order processors. With the order peeker you will see the first
pending order that need processing at any time.
The following figure shows how the scenario works.
Page 65
Figure 36
Message Buffer scenario
This exercise will show how to create, connect and delete a Message Buffer. In addition, you will learn
how to peek/lock, release/lock and retrieve messages from a buffer.
This exercise will expose the usage of the following classes:
MessageBufferPolicy
MessageBufferClient
TypedMessageConverter
TransportClientEndpointBehavior
Note: To verify that each step is correctly performed, it is recommended to build the solution at the
end of each task.
Task 1 – Creating the Order Peek
Page 66
1. Open Microsoft Visual Studio 2008 from Start | All Programs | Microsoft Visual Studio 2008 |
Microsoft Visual Studio 2008.
2. Open the MessageBuffer.sln solution file located at Ex05-MessageBuffer\begin\ in the Source
folder of the lab.
3. Add a new method called EnsureMessageBufferExists that will verify if the message buffer is
already created; and if not, it will create a new one. To do this, in Solution Explorer, double-
click the Program.cs file under the OrderPeek project and paste the following code at the end
of the Program class.
(Code Snippet - Introduction to Service Bus Lab - Ex05 EnsureMessageBufferExists method)
C#
private static MessageBufferClient
EnsureMessageBufferExists(TransportClientEndpointBehavior endpointBehavior,
Uri messageBufferUri, ref MessageBufferPolicy messageBufferPolicy)
{
MessageBufferClient client;
try
{
client = MessageBufferClient.GetMessageBuffer(endpointBehavior,
messageBufferUri);
messageBufferPolicy = client.GetPolicy();
Console.WriteLine("Using existing message buffer.");
return client;
}
catch (EndpointNotFoundException)
{
// Not found; absorb and make a new message buffer below.
// Other exceptions get bubbled up.
}
catch (FaultException)
{
}
client = MessageBufferClient.CreateMessageBuffer(endpointBehavior,
messageBufferUri, messageBufferPolicy);
Console.WriteLine("New message buffer created.");
return client;
}
If the preceding method successfully creates the Message Buffer, it will create it using the
provided message buffer policy.
Note: The MessageBufferClient static class contains methods to get and create a message
buffer.
Page 67
4. Modify the Main method, to create a MessageBufferPolicy and to invoke the
EnsureMessageBufferExists method you have added in the previous step. You have to pass the
endpoint behavior, the message buffer URI, and the message buffer policy as parameters. To do
this, paste the following code below the corresponding comment.
(Code Snippet - Introduction to Service Bus Lab - Ex05 Invoke EnsureMessageBufferExists
method)
C#
private static void Main()
{
...
// Get Message Buffer URI
Uri messageBufferUri = ServiceBusEnvironment.CreateServiceUri("http",
serviceNamespaceDomain, "OrderMessageBuffer");
Console.WriteLine("Message Buffer Address: " +
messageBufferUri.AbsoluteUri);
Console.WriteLine();
// Message Buffer Policy
MessageBufferPolicy messageBufferPolicy = new MessageBufferPolicy();
messageBufferPolicy.Authorization = AuthorizationPolicy.Required;
messageBufferPolicy.MaxMessageCount = 10;
messageBufferPolicy.ExpiresAfter = TimeSpan.FromHours(1); // messages in
the message buffer expire after 1 hour
messageBufferPolicy.TransportProtection = TransportProtectionPolicy.None;
MessageBufferClient messageBufferClient =
EnsureMessageBufferExists(endpointBehavior, messageBufferUri, ref
messageBufferPolicy);
}
Note: When creating a Message Buffer, the message buffer policy is one of the required
parameters. This policy is modeled by the MessageBufferPolicy class, which provides the
functionality to set the security type used on the Message Buffer as well as the messages
lifespan and what to do when the buffer fills up with messages (OverflowPolicy). Currently,
the only available action is to reject the incoming message by faulting the message back to the
sender.
The following table shows the different settings that you can configure with the
MessageBufferPolicy class.
Page 68
MessageBufferPolicy Properties Description
ExpireAfter This is the lifespan of the message buffer.
MaxMessageCount The maximum number of messages that can be in the message
buffer before the overflow policy activates.
OverflowPolicy What to do when the buffer fills up with messages. Currently, the only
available action is to reject the incoming message by faulting the
message back to the sender.
TransportProtection The transport protection refers to the level of end-to-end security that
must be used.
Authorization Specifies the type of authorization required for sending and receiving
messages on a Buffer. You can choose between “NotRequired”,
“Required”, “RequiredToReceive” and “RequiredToSend”.
5. Next, add the logic to peek the pending submitted order from the Service Bus using the
PeekLock method of the MessageBufferClient class, which retrieves the first available message
from the Message Buffer, and locks that message on the buffer. In addition, uses the
ReleaseLock method to release the message. To do this, paste the following code below the
code inserted in the previous step.
(Code Snippet - Introduction to Service Bus Lab - Ex05 Order Peek Logic)
C#
// Message converter for Order messages
TypedMessageConverter orderConverter =
TypedMessageConverter.Create(typeof(Order), "SubmitOrder");
while (true)
{
try
{
Message message = messageBufferClient.PeekLock();
if (message != null)
{
Console.WriteLine("Pending Order:");
Order order = orderConverter.FromMessage(message) as Order;
if (order != null)
{
Console.WriteLine(string.Format(CultureInfo.InvariantCulture,
"- {0} ({1})", order.Product, order.Quantity));
}
messageBufferClient.ReleaseLock(message);
}
}
Page 69
catch (TimeoutException)
{
Console.WriteLine("No pending orders...");
}
catch (FaultException)
{
}
Console.WriteLine("Sleeping...");
Thread.Sleep(10000);
}
Note: Notice that the Message Buffer is stored in a MessageBufferClient instance. This class
has functionality to manipulate the message buffer. It contains methods to send and receive
messages. In addition, it contains methods peek/lock a message, which is held temporarily by
the Message Buffer, but “locked” so that no one else can retrieve it. Nevertheless, you or
other clients can still pull other message from the Message Buffer. The message then goes
back into the Message Buffer, where it can be retrieved again. The Message Buffer releases
the lock message if the client does not explicitly instruct to delete the locked message before
the timeout expires. In the OrderPeek project of the solution, the MessageBufferClient class is
used to peek/lock and release a message.
The default timeout of a locked message is one minute. If the call does not return in that time,
the message will be released.
Task 2 – Creating the Order Submitter
1. Add code in the project’s Main method to get the existing Message Buffer. To do this, in
Solution Explorer, double-click the Program.cs file under the OrderSubmitter project and paste
the following bolded code in the Main method as shown below.
(Code Snippet - Introduction to Service Bus Lab - Ex05 Get Message Buffer )
C#
private static void Main()
{
...
// create the URI for the Message Buffer
Uri messageBufferUri = ServiceBusEnvironment.CreateServiceUri("http",
serviceNamespaceDomain, "OrderMessageBuffer");
Console.WriteLine("Message Buffer address: " +
messageBufferUri.AbsoluteUri);
Page 70
// Get existing Message Buffer
MessageBufferClient messageBufferClient =
MessageBufferClient.GetMessageBuffer(endpointBehavior, messageBufferUri);
Console.WriteLine("Using existing message buffer");
}
Note: Notice that the Message Buffer is stored in a MessageBufferClient instance. This class
has functionality to manipulate the message buffer. It contains methods to send and receive
messages among others.
2. Add the logic to enter the orders and submit them to the Service Bus, where they will be
captured and processed by the Order Processors (the processors application will be created
later on this exercise). To do this, paste the following code below the code inserted in the
previous step.
(Code Snippet - Introduction to Service Bus Lab - Ex05 Orders Submission)
C#
private static void Main()
{
...
Console.WriteLine();
Console.WriteLine("Enter your order in the form of '[Quantity] [Product]'
and press [ENTER]");
Console.WriteLine("Enter 'exit' and press [ENTER] to exit");
string input = Console.ReadLine();
while (input.ToUpperInvariant() != "EXIT")
{
var order = ParseOrder(input);
if (order != null)
{
try
{
// Message converter for Order messages
TypedMessageConverter orderConverter =
TypedMessageConverter.Create(typeof(Order), "SubmitOrder");
var message = orderConverter.ToMessage(order);
messageBufferClient.Send(message);
Page 71
Console.WriteLine("Order Message Sent!");
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
}
else
{
Console.WriteLine("Invalid format");
Console.WriteLine("Please use [Quantity] [Product]. Ex: '200
NAILS'");
}
input = Console.ReadLine();
}
}
Note: Notice that the preceding code also validates that each order is entered in the correct
format: [Quantity] [Product].
Task 3 – Creating the Order Processor
1. Add code in the project’s Main method to get the existing Message Buffer if it exists, or create a
new one if necessary. To do this, in Solution Explorer, double-click the Program.cs file under
the OrderProcessor project and paste the following bolded code that defines a Message Buffer
Policy and calls the EnsureMessageBufferExits method in the Main method as shown below.
C#
private static void Main()
{
...
// create the URI for the Message Buffer
Uri messageBufferUri = ServiceBusEnvironment.CreateServiceUri("http",
serviceNamespaceDomain, "OrderMessageBuffer");
Console.WriteLine("Message Buffer address: " +
messageBufferUri.AbsoluteUri);
// Message Buffer Policy
MessageBufferPolicy messageBufferPolicy = new MessageBufferPolicy();
messageBufferPolicy.Authorization = AuthorizationPolicy.Required;
messageBufferPolicy.MaxMessageCount = 10;
Page 72
messageBufferPolicy.ExpiresAfter = TimeSpan.FromHours(1); // messages in
the message buffer expire after 1 hour
messageBufferPolicy.TransportProtection = TransportProtectionPolicy.None;
MessageBufferClient messageBufferClient =
EnsureMessageBufferExists(endpointBehavior, messageBufferUri, ref
messageBufferPolicy);
}
2. Create a message converter to convert from the message to an order-type message. To do this,
paste the following bolded code below the corresponding comment.
C#
private static void Main()
{
...
// Message converter for order messages
TypedMessageConverter orderConverter =
TypedMessageConverter.Create(typeof(Order), "SubmitOrder");
}
Note: The TypedMessageConverter class provides the functionality to convert a typed
message to an untyped message and viceversa. A typed message is an instance of a type that
has the MessageContractAttribute attribute annotated. An untyped message is one that is an
instance of the Message class.
3. Add code to retrieve a message from the Message Buffer and convert it to an Order instance
using the TypedMessageConverter converter created in the previous step. In addition, add
code to delete the Message Buffer using the DeleteMessageBuffer method of the
MessageBufferClient when typing ‘delete buffer’ in the client console application, and ‘exit’ to
close the console. To do this, add the following bolded code in the Main method as shown
below.
(Code Snippet - Introduction to Service Bus Lab - Ex05 Retrieve Message from the Message
Buffer code)
C#
private static void Main()
{
...
TypedMessageConverter orderConverter =
TypedMessageConverter.Create(typeof(Order), "SubmitOrder");
Page 73
Console.WriteLine("Type at any time 'delete buffer' to destroy the Message
Buffer or 'exit' to close the console.");
string command;
bool running = true;
do
{
ThreadPool.QueueUserWorkItem(state =>
{
while (running)
{
try
{
// Until a new message is retrieved, the Retrieve method won't
return (unless the default timeout expires)
Message message = messageBufferClient.Retrieve();
// Convert buffer message to Order type
Order order = orderConverter.FromMessage(message) as Order;
if (order != null)
{
ProcessOrder(order);
}
}
catch (TimeoutException)
{
Console.WriteLine("No pending orders to be processed.");
Thread.Sleep(100000);
}
catch (FaultException)
{
}
}
});
command = Console.ReadLine();
} while ((command.ToLowerInvariant() != "delete buffer") &&
(command.ToLowerInvariant() != "exit"));
running = false;
if (command.ToLowerInvariant() == "delete buffer")
{
messageBufferClient.DeleteMessageBuffer();
Console.WriteLine("Message Buffer Deleted");
Console.WriteLine("Press any key to exit");
Console.ReadLine();
Page 74
}
}
Note: The actual order process is not being done, the ProcessOrder method executes the
Thread.Sleep method to simulate the processing of the order.
Verification
In order to verify that you have correctly performed every step of this exercise, proceed as follows.
1. Run the Order Peeker. To do this, right-click the OrderPeek project, point to Debug and select
Start New Instance. When prompted, provide the Service Namespace Domain you have set up
during the provisioning process. After that, enter the Issuer Name and Issuer Secret that were
generated for the Service Namespace Domain. At this point, the console should indicate that a
new Message Buffer was created.
Figure 37
The Order Peek console created the Message Buffer and started listening for messages
Note: The Order Peek console will look for the Message Buffer and, if not found, it will create
a new one.
2. Run the Order Submitter. To do this, right-click the OrderSubmitter project, point to Debug and
select Start New Instance. Provide the Service Namespace Domain you have set up during the
provisioning process, and then the Issuer Name and Issuer Secret. At this point, the Order
Submitter console should indicate that it will use the existing Message Buffer—the one created
by the Order Peek console— and will prompt you to enter orders.
Page 75
3. Generate a few random orders in the console; for example:
◦ 200 nails [enter]
◦ 1 hammer [enter]
◦ 1 wrench [enter]
Figure 38
The submitted orders
Note: The OrderPeek console should show the first submitted order item. It will continuously
show the orders with pending processing.
4. Notice how the Peek console is showing the first message sent by the Order Submitter console
(the next message to be processed), which in this case is the order “200 nails”.
Page 76
Figure 39
The Order Peek application is showing the next message to be processed.
5. Open an instance of the Order Processor application and provide the Service Namespace
Domain, Issuer Name and Issuer Secret as you have done in the previous steps. The console
should show the processing of the three pending order as shown in the following figure.
Figure 40
The Order Processors processed the three pending orders
6. Open one or more new instances of the OrderProcessing console and start sending new orders
from the OrderSubmitter.
Page 77
Note: The processing of the new orders should balance between the OrderProcessor consoles.
The more OrderProcessor instances, the orders will not stay a lot of time in the Message
Buffer.
7. Close the OrderPeeker console. Type “exit” and press ENTER to close each of the running
OrderProcessor consoles, except for the last one where you should use “delete buffer” instead
to delete the Message Buffer and exit the console. In the OrderSubmitter console type “exit”
and press ENTER to close the console and end this verification.
Summary
By completing this Hands-On Lab you have learnt how to create a Service NameSpace Domain, how to,
expose and consume your services through the Service Bus. Different types of bindings and connections
modes to establish communications between clients and services were exposed: netTcpRelayBinding,
Hybrid and Relayed modes, multicasting with netEventRelayBinding, ws2007HttpRelayBinding. In
addition, you have learnt how to expose a Metadata Exchange (MEX) endpoint through the Service Bus ,
how to use X.509 certificates for message confidentiality, and how to make a REST Service expose binary
data through the Service Bus. Finally, you've learnt how to manipulate a Message Buffer in .NET
Services based on an order-processing scenario.
Page 78