DarksideCookie

Come to the dark side...we have cookies!

Using Azure Service Bus relaying for REST services

I am now about a week and a half into my latest Azure project, which so far has been a lot of fun and educational. But the funky thing is that I am still excited about working with the Service Bus, even though we are a week and a half into the project. I guess there is still another half week before my normal 2 week attentions span is up, but still!
So what is so cool about the bus, well, my last 2 posts covered some of it, but it is just so many cool possibilities that open up with it.
This post has very little to do with what I am currently working on, and to be honest, the sample is contrived and stupid, but it shows how we can use REST based services with the bus.
But before I start looking at code, I would suggest reviewing the previous post for details regarding NuGet package for the Service But stuff as well as some note about setting up your project for Azure development as well as setting up the Azure end of things.
Once that is done, it is time to look at the code, which in this case, once again, will be implemented in a console applications.
Start by adding a new interface, remember, the bus is all about WCF services, and WCF services are all about interfaces. I am calling my interface IIsItFridayService. It has a single method called IsIt(). It takes no parameters, and returns a Stream. I also add a ServiceContract attribute as well as a OperationContract one. These are the standard WCF attributes unlike the last attribute I add, which is called WebGet. It is a standard WCF attribute as such, but it is not used as much as the other two which are mandatory. And on top of that, it is located in another assembly that you need to reference, System.ServiceModel.Web. In the end it looks like this
[ServiceContract(Name = "IIsItFriday", Namespace = "http://chris.59north.com/azure/restrelaydemo")]
public interface IIsItFridayService
{
[OperationContract]
[WebGet(UriTemplate = "/")]
Stream IsIt();
}
The WebGet attribute has a UriTemplate that defines the template to use when calling it, pretty much like routes in ASP.NET MVC. You can find out more about it here.
Now that we have an interface/contract, we obviously need to implement it. So a new class needs to be created, and it needs to implement the interface we just designed.
The implementation for my IsItFriday service is ridiculously simple. It uses a standard HTML format string, and inserts a yes or no statement into it based on the day of the week. It then converts the string into a MemoryStream and return that. Like this
public class IsItFridayService : IIsItFridayService
{
private static string ReturnFormat = "<html><head><title>{0}</title></head><body><h1>{0}</h1></body>";

public Stream IsIt()
{
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";

var str = DateTime.Now.DayOfWeek == DayOfWeek.Friday ? "Yes it is!" : "No it isn't...";
return new MemoryStream(Encoding.UTF8.GetBytes(string.Format(ReturnFormat, str)));
}
}
The only thing that is out of the ordinary is the use of the WebOperationContext class. Using this, I change the content type of the response to enable the browser to interpret it as HTML. If you were to return JSON or XML, then you would set it to that…
The reason for returning a Stream instead of a string is that when we return a string, it will be reformatted and surrounded with an XML syntax. A Stream is rendered as is…
Ok, now there is a service contract and a service, I guess it is time to host it in the console app. This is done by creating a new WebServiceHost, passing in the type of the service to be hosted. Next we call Open() to open to service ports.
However, as this is a console app, we also need to make sure to keep the thread busy and alive. I do this with a simple Console.ReadKey(), which is followed by host.Close() to make sure we close the host, and thus service bus connection, before we leave the app
class Program
{
static void Main(string[] args)
{
var host = new WebServiceHost(typeof(IsItFridayService));

host.Open();

Console.WriteLine("Service listening at: " + host.Description.Endpoints[0].Address);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

host.Close();
}
}
That’s it! Almost at least… There is obviously a config file somewhere in play here. The host needs configuration, and there isn’t any here.
In the previous post, I did some of the config in code, not all though even though I could. In this case, I have left it all in the config to make the code easier to read.
The config looks like this
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="DarksideCookie.Azure.ServiceBusDemo.RelayingREST.IsItFridayService">
<endpoint contract="DarksideCookie.Azure.ServiceBusDemo.RelayingREST.IIsItFridayService"
binding="webHttpRelayBinding" address="http:// [ NAMESPACE ] .servicebus.windows.net/IsItFriday/" />
</service>
</services>
<bindings>
<webHttpRelayBinding>
<binding>
<security mode="None" relayClientAuthenticationType="None" />
</binding>
</webHttpRelayBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior>
<transportClientEndpointBehavior credentialType="SharedSecret">
<clientCredentials>
<sharedSecret issuerName="owner" issuerSecret=" [ SECRET ] " />
</clientCredentials>
</transportClientEndpointBehavior>
<serviceRegistrySettings discoveryMode="Public"/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<bindingExtensions>
<add name="webHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</bindingExtensions>
<behaviorExtensions>
<add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="serviceRegistrySettings" type="Microsoft.ServiceBus.Configuration.ServiceRegistrySettingsElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
And that is a LOT of config for something this trivial. I know! But it all makes sense to be honest. Let’s look at it one part at the time, ignoring the <startup /> element as it just tells the system that it is a .NET 4 app.
I’ll start from below. The <extensions /> element contains new stuff that the machine config doesn’t know about.  On this case, it contains one new binding type, and two new behaviors. The binding is the webHttpRelayBinding, which is used when relaying HTTP calls through the service bus. And the 2 behaviors consists of one that handles passing credentials from the service to the service bus, and one that tells the bus to make the service discoverable in the service registry.
The next element is the standard <behaviors /> element. It configures the behaviors to use for the endpoint. By not naming the <behavior /> element, it will be the default and will be used by all endpoints that do not specifically tell it to use another one. The behavior configuration sets up the 2 new extensions added previously.
When trying this, you will have to modify the downloaded config and add your shared secret in here…
Next element in the tree is the <bindings /> one. It configures the webHttpRelayBinding to use no security, that means require no SSL and so on, as well as not use relay any client credentials. This last part will make sure that you do not get a log in prompt when browsing to the service.
And the final element is the service registration with its endpoint…
So, what does spinning this application up do for us? Well, it looks like this
image
Which is far from impressive. However, if you direct a browser to the url displayed in the window, you get this
image
Cool! Well…at least semi cool. If we start thinking about it, I think we would agree. I have managed to create a local application (Console even) that can be reached from any browser in the world through the Service Bus.
It does have some caveats, like the fact that it is pretty specific about the URL for example. It has to end with “/, and it doesn’t take any parameters. The latter part however can be changed, and the service could be turned into a full blown REST service with all the bells and whistles…
That was it for me this time! I hope it has shown you a bit more of the power of the bus!
Cheers!
Posted: Oct 06 2011, 18:47 by ZeroKoll | Comments (0) |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: .NET development | Azure | WCF
Manage post: :)

Pingbacks and trackbacks (1)+

Comments are closed