On the flip side of the cloud-coin, we have the Azure .NET Services platform (hell, there’s more than two sides to Azure, but those two are the ones I feel are most noteworthy as of now).

The concept and purpose for the Azure .NET Services platform is rather easy to grasp: It allows you the opportunity to host Windows Communication Foundation-based services on the cloud. Achieving this requires the use of the multiple components that make up the Azure .NET Services platform, such as the Access Control and Services Bus services. Using these services will provide you with a secure intermediary interconnect you can use to provide endpoints for client and server. This allows the developer the ability to spend more time on the service itself, not the additional logic required in dealing with various network topologies.

Much of the Azure .NET Services platform is based on the WCF core libraries, but the use of these assemblies alone are not enough to get the services hosted and working the cloud. There are several Azure .NET Services-specific assemblies that you must become familiar with and use in order to get your service out there. In this article I’m going to go over the use of the Azure .NET Services assemblies, as well as take a general look at how the services work as a whole.

Much like my article on the SQL Data Services end of the cloud, this marks the beginning of the series through which I’ll be developing a library that will be used to get the most out of this service Microsoft is offering.

I. Azure .NET Services Platform Overview: Service Bus and Access Control

The Azure .NET Services platform is made up of several components:

  1. Service Bus
  2. Access Control Service
  3. Workflow Service

We’ll look at the Workflow service later; for now we’ll concentrate on the other two, as the use of one pretty much requires the use of the other.

The purpose of the Service Bus is to consolidate all of the possible network topologies that exist into a single communication infrastructure. This infrastructure can then be used by any peer-to-peer or connected applications we write for creating connections. Ideally, this would allow us the opportunity to skip the additional development and time required in order to account for varying and complex network topologies. Therefore, our goal here is to determine if the amount of time saved by using the Services Bus for providing communication between client and service is greater than the time required to implement the additional logic that allows a .NET service to be hosted on Azure.

The Access Control service comes into play here when we need to consider security and authentication management. It is a publicly accessible service based on Security Token Service or STS. The STS authenticates the client and the service wishing to use the Service Bus. Once credentials are received by the STS, a security token is issued to the client and service that must be included with all messages sent through the Service Bus. Configuration of the Access Control service can be achieved either through the Azure Portal or in your code. The Portal is useful when you need to configure more advanced permissions; for our purposes, we can do everything we need to in our code.

It has been stated before that use of Azure’s .NET Services allows you to bypass all the various problems caused by differing network topologies, such as the state of NAT with DNS. Machines on public IP’s are accessible via DNS, however as soon you throw NAT into the mix, you can forget about any sort of DNS resolution. Each solution on Azure determines the shape of a naming tree provided to it by Azure’s Naming System. All paths through this naming tree have projections that are directly mappable to a URI. Because the root of the naming tree is resolvable by DNS, we effectively have a naming system that complements DNS.

The interesting thing about the Azure naming system is that, unlike DNS naming, the endpoints of the naming tree one encounters while moving from the host portion of the URI are completely host-agnostic. Access to this naming system is provided through the Service Registry, which provides us with service discovery via navigation of the naming hierarchy that manifests itself as a nested tree of Atom 1.0 feeds. The root feed of the naming hierarchy is located at http://servicebus.windows.net/services/nameOfYourSolution. This is the current address, I’d expect it to change actually throughout time (especially when Azure goes from beta to release), which goes to show why it is important never to hardcode that address in your services (I’ll show you what to do instead later).

The most important technique used for connectivity is the Relay service. This service works by the user starting a secured and authenticated TCP outbound connection into the Relay service, telling the Relay service the location we want to start listening in the naming tree. An HTTP-based multiplexing polling system is used to exploit the fact that most of the high security networking environments block all outbound traffic except for HTTP. Unfortunately, this method only supports unicast and multicast datagram communication. If you pair two unicast connections with mutually reversed client and server roles together, however, you can achieve bidirectional connectivity.

The key here is the type of binding your service and client use; you are probably already familiar with the various WCF bindings. You will see complements of each binding in the Microsoft.ServiceBus library (one of those assemblies I mentioned earlier), such as the NetTcpRelayBinding (compared to the standard NetTcpBinding) and the WebHttpRelayBinding (compared to th standard WebHttpBinding). You may notice one class that isn’t related to anything in the standard WCF libraries: NetEventRelayBinding. This allows you to enable clients to be event publishers and listeners as subscribers. This is an interesting feature, and I’ll be demonstrating its use in a bit.

II. Basic Use of .NET Services with the NetTcpRelayBinding

I’m going to show and provide you with a sample that utilized the NetTcpRelayBinding, a binding which is very similiar to what’s offered in the WCF core libraries (NetTcpBinding). Instead of listening on the local TCP socket, our listener is placed on a publicly reachable (and possibly discoverable) endpoint in the Service Bus fabric. I’m looking at NetTcpRelayBinding due to it being the practical choice of binding for any simple service listening in the Service Bus.

There are three types of connection modes one can use with NetTcpRelayBinding:

  • Relayed
  • Hybrid
  • Direct

The Relayed mode is obvious, and means that all communication is relayed through the Service Bus. The Hybrid mode is a more advanced type, and works by establishing a direct connection between service and client endpoints while relaying all other communication through the bus. Once a direct connection is established, the mode is upgraded to Direct mode, which results in no relaying of any communication through the Service Bus. The Hybrid and Direct modes are for more advanced situations than what I’ll be looking at today, and will be covered later. It is also worth saying that these two modes (especially Direct) should not be considered to be in their final form or state (meaning, there will most likely be some large changes to how they work before release).

Creating a service that listens on the Service Bus requires the completion of the following:

  1. Referencing the .NET Services assemblies (Microsoft.ServiceBus.dll and Microsoft.AccessControl.Management.Dll)
  2. Creating a WCF service contract
  3. Creating an implementation of the service contract
  4. Add the logic exposing the service through the Service Bus by construction of a proper Service Bus URI and through the use of the NetTcpRelayBinding type of binding. This also requires the creation of a service configuration file.

To create the WCF service contract, we apply the ServiceContract attribute to an interface, marking it as a service contract (assume the following is in a file named IOmniTutorialContract.cs):


[ServiceContract(
    Name="OmniTutorialContract",
    Namespace="http://azure.omniscientist.com/OmniTutorial"
)]
public interface IOmniTutorialContract
{
    [OperationContract]
    string DoSomething(string whatToDo);
}

As you can see above, we defined an operation of the contract that “does something” with a string provided by the client, and then returns a meaningful string.

Next, we need to implement this interface we just defined, so let’s create a class named OmniTutorialService.cs that will implement our WCF service:


[ServiceBehavior(
    Name = "OmniTutorialService",
    Namespace="http://azure.omniscientist.com/OmniTutorial"
)]
public class OmniTutorialService : IOmniTutorialContract
{
    public string DoSomething(string whatToDo)
    {
        ...
        return "This is a really valuable piece of information.";
    }
}

We now implemented our WCF service with the above class. As you can see, the implementation “does something” and returns some really valuable information.

Up until now, all of what we’ve been doing isn’t too different from what you would normally do with WCF. That’s about to change, as we’re now going to look at how you go about actually hosting this WCF service through the Service Bus.

This is, of course, going to vary for whatever the hell it is that you’re doing, but there are a few things we need to always do. First, we need to construct the appropriate URI to the Service Bus for your solution:

Uri address = new Uri(
    String.Format("sb://{0}/services/{1}/OmniTutorialService/",
        ServiceBusEnvironment.DefaultRelayHostName, solutionName));

To expose our OmniTutorialService as a WCF service, we then create a ServiceHost object and then open a connection:

ServiceHost host = new ServiceHost(typeof(OmniTutorialService), address);
host.Open();

At this point, our service would now be listening on the Service Bus. Exiting the program would result in a host.Close() which would disconnect us from the cloud. So, we’ll ideally want to install our service as an actual service that can run in the background.

Note, that I said we “would” be listening on the Service Bus. Before we get all excited, we need to create an application configuration and set it up appropriately.

One of the important things we’ll be defining in our app.config is how we authenticate. You can either authenticate via CardSpace, a traditional provided username/password, or through the use of a X509 certificate. Before we get into that, we’ll want to define our services configuration section:

<services>
    <service name="Omniscientist.Services.OmniTutorialService">
        <endpoint       name="RelayEndpoint"
                         contract="Omniscientist.Services.IOmniTutorialContract"
                         binding="netTcpRelayBinding"
                         bindingConfiguration="default"
                         behaviorConfiguration="authenticationBehavior"
                         address=""/>

The behavior configuration element will contain the value that points to the behavior that defines the type of authentication we want. For now, let’s just look at the traditional way of authentication, and then CardSpace.

The behavior section for just providing a username and password is something like:

<behaviors>
    <endpointBehaviors>
        <behavior name="usernameAndPasswordBehavior">
            <transportClientEndpointBehavior credentialType="UserNamePassword">
                <clientCredentials>
                    <userNamePassword userName="nameOfSolution" password="password"/>
                </clientCredentials>
            </transportClientEndpointBehavior>
        </behavior>
    </endpointBehaviors>
</behaviors>

Of course, you can just initialize a TransportClientEndpointBehavior object in code and determine the username and password there, if the need arises. Now, this is how we do it with CardSpace:

<behaviors>
    <endpointBehaviors>
        <behavior name="cardSpaceBehavior">
            <transportClientEndpointBehavior credentialType="CardSpace"/>
        </behavior>
    </endpointBehaviors>
</behaviors>

As skeptical as I was about the whole CardSpace thing, that technology could turn out to be pretty useful here. Just remember you need to set up CardSpace credentials on the Azure portal before doing anything here.

To finish things off, we need to just configure our simple netTcpRelayBinding setup:

<bindings>
    <netTcpRelayBinding>
        <binding name="default"/>
    </netTcpRelayBinding>
</bindings>

This is all you need to create a listener on the Service Bus.

To create the client side of all of this, we need to do the following:

  1. Create the OmniTutorialService proxy
  2. Provide the logic which will consume the WCF service hosted at the Service Bus

There shouldn’t be much difference at this point from creating a client for just plain ol’ WCF services. We’ll see differences when implementing the logic required to consume the service at the Service Bus, however. In order to achieve that, we need to create a correct Uri, set that as the endpoint address, and then create a channel to the endpoint:

//Create the Uri the same way as before

EndpointAddress address = new EndpointAddress(uri);

ChannelFactory<IOmniTutorialChannel> channelFactory =
    new ChannelFactory<IOmniTutorialChannel>("RelayEndpoint", address);

IOmniTutorialChannel channel = channelFactory.CreateChannel();

channel.Open();

channel.DoSomething("I've got sumthin ta say...");

Finally, we shouldn’t forget that we need to provide an app.config for the client as well. For this simple service, the configuration required is thankfully short. We’re basically just going to set up the binding and the client’s endpoint.

<client>
    <endpoint     name="RelayEndpoint"
                  contract="Omniscientist.Services.IOmniTutorialContract"
                  binding= "netTcpRelayBinding"
                  bindingConfiguration="default"
                  address=""/>
</client>

<bindings>
    <netTcpRelayBindings>
        <binding name="default"/>
    </netTcpRelayBindings>
</bindings>

You now have a working service hosted at the Service Bus that is accessible from a client. This concludes this basic and short introduction to the .NET Services Platform on Azure. My next article on this will be on a much more advanced level; I’ll assume the reader will have gained knowledge from other sources before taking a peek at it.

Matt Weber

I'm the founder of Bad Echo LLC, which offers consulting services to clients who need an expert in C#, WPF, Outlook, and other advanced .NET related areas. I enjoy well-designed code, independent thought, and the application of rationality in general. You can reach me at matt@badecho.com.

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
   
© 2012-2013 Matt Weber. All Rights Reserved. Terms of Use.