The last couple of evenings I spent some time getting familiar with the .NET Services and the Service Bus in particular. Here is a story of how I got my sample service to be available on the .NET Service Bus.
I assume that you are familiar with the .NET Service Bus already; otherwise you can read some good articles on MSDN (documentation and two articles) and Clemens Vasters’ blog.
My goals were easy: what does it take to get a pretty standard WCF service up and running using the .NET Service Bus. For completeness sake, this is the service contract (sticking with my ever lasting theme of gaming):
public interface IGameServerManagement
GameServerStatus RetrieveServerStatus(IPAddress address, int port);
I wanted to have the request/reply styled service implementation available with message security enabled. Like myself you will need a .NET Services account to be able to use the .NET Services (Service Bus and Access Control service) and have a so-called solution (mine is named “KillerApps”). You will find that solution names must be globally unique, so don’t be late and find out your intended name is already taken!
Hosting and exposing your service
First of all you need to have the service host register your service endpoint on the service bus. A lot of the plumbing is taking care of by the NetTcpRelayBinding, which does all the negotiation with the bus. All we have to do is choose an endpoint on the service bus and authenticate ourselves to the bus. For simplicity I chose the following name “GameServerService” as the significant part of the endpoint address.
To create the complete endpoint address you can use a helper method:
Uri address = ServiceBusEnvironment.CreateServiceUri("sb", solutionName, "GameServerService");
which will generate an URI like so sb://KillerApps.servicebus.windows.net/GameServerService. The italic/bolded parts are the pieces that get filled in for you. The scheme corresponds to the type of relay binding. For TCP it will be sb, for basic, WS, federation and web HTTP bindings it will be http or https.
The service host needs some preparations that can be done through code or config. I did parts in both.
string solutionName = "KillerApps";
string solutionPassword = "test1234"; // Nope, not my real password and you should replace it with your own
// Create the credentials object for the endpoint.
TransportClientEndpointBehavior userNamePasswordServiceBusCredential = new TransportClientEndpointBehavior();
userNamePasswordServiceBusCredential.CredentialType = TransportClientCredentialType.UserNamePassword;
userNamePasswordServiceBusCredential.Credentials.UserName.UserName = solutionName;
userNamePasswordServiceBusCredential.Credentials.UserName.Password = solutionPassword;
// Create the service host reading the configuration.
ServiceHost host = new ServiceHost(typeof(GameServerService), 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)
// Open the service.
The approach above is from the Getting Started sample in the .NET Services SDK for July 2009. Nothing fancy, just with some fixes:
- The sample duplicates the line for setting the username instead of one for the password.
- Also, the sample uses the old URIs for the service bus endpoints. You can now use the helper method).
A quick disclaimer: do not store your password in your code or config like this. Keep it safe and encrypted.
A service that wants to expose an endpoint on the Service Bus always need to authenticate, so not any odd service can claim an endpoint with your solution name in it. Likewise, the client needs to authenticate, so the service bus can check whether it is allowed to access a particular service endpoint. The endpoint behavior for password based authentication is prepared and added to all endpoints. The behavior takes care of passing a username (always the name of the solution) and password to the bus.
There are other authentication types, such as CardSpace and certificates. The place to configure each of these authentication types is in another part of the .NET Services: the Access Control Service. That’s a topic for another post, but when you are looking for some guidance on the combination of CardSpace and the bus I can recommend the Hands-on Lab “.NET Services: Introduction to the Access Control Service” from the Geneva Training Kit. The host of your service chooses the authentication type it wants to use and the Access Control Service will perform the authentication.
Also, the service will be added to the registry discoverable for everyone through the ServiceRegistrySetting endpoint behavior.
The other part needed for successful hosting resides in the config file. The service’s configuration holds two endpoint definitions:
<service behaviorConfiguration="GamingServiceBehavior" name="GamingServiceLibrary.GameServerService">
<endpoint binding="netTcpRelayBinding" bindingConfiguration="default" contract="GamingServiceLibrary.IGameServerManagement">
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
Looking at this config section you can see two endpoints: one for the actual service contract implementation and one for metadata exchange. The base address in the host element does not really matter for the first endpoint, because we are providing the sb:// specific adress in the code. Also, both the binding and the service have configurations that are being referred to.
The binding has this configuration:
<binding name="default" connectionMode="Relayed">
<message clientCredentialType="UserName" algorithmSuite="Default" />
It specifies the connection mode of the service to the service bus and the client later on. Relayed means a client will be relayed through the service bus. Direct and Hybrid are the other options. The former allows a direct connection between client and service after service bus negotiation (which might not turn out to be possible). The latter is a mode where direct is attempted with a fallback to Relayed when direct connections fail.
The <security> element configures the security of the messages. This is completely orthogonal to the way authentication has occurred. Security is optional to protect the communication between client and service, whereas authentication does not protect but is mandatory for exposing a service on the bus.
Hosting and exposing your service on the .NET Service Bus requires you to use one of the special Relay binding that are new in the Microsoft.ServiceBus assembly. Upon connection, the binding will negotiate the details of the endpoint with the host. In the process the binding will attempt to authenticate the host to the bus.
Next time we will take a look at how to enable message security and I will also explain the security configuration, the endpoint behavior and <identity> element that is skipped over for now.