Recently Microsoft has released Windows Azure Tools for Visual Studio November 2009 CTP. which includes the latest Windows Azure SDK binaries and tools for Visual Studio 2010 Beta 2. There are some new features within this tools such as Role based Windows Azure development. Now developers can create a cloud service project that contains multiple roles, there are two mainly role categories supported in this release – Web Role and Worker Role. Web Role means the application consumes the Azure service as a Web application, for example, an ASP.NET Web application, ASP.NET MVC 2.0 application or WCF Web Service application; the Worker Role means the application works as a background process. The following screenshot shows the supported Roles when you create a cloud application in Visual Studio.
Another useful SDK for Windows Azure platform is AppFabric. you can download the AppFabric SDK here. The AppFabric SDK contains the Service Bus assemblies, which enables communication between client and servers regardless the network device and infrastructure. If you want to develop a service using Service Bus, you may have problems to deploy your project to the Windows Azure platform because Microsoft has not released the Visual Studio support in this AppFabric SDK. I am planning to use Service Bus to host a cloud-enabled IM application, I wrote a simple solution to test the functionality. The application works well in the local machine, but unfortunately, when I deploy the package to the Windows Azure, the Worker Role failed to initialize, sometimes the status is “stopped” after deployment. I followed the Windows Azure Training Kit to create the Work Role application, but why this failed to start?
The origin code
Here is the application structure I created:

1. The WCF service class and interface (ICloudIMService.cs and CloudIMService.cs):
Code Snippet
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.Serialization;
- using System.ServiceModel;
- using System.Text;
-
- namespace CloudIM.ServiceContract
- {
- // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ICloudIMService" in both code and config file together.
- [ServiceContract(Name = "CloudIM.WorkerRole.CloudIMService", Namespace = "cloudim.cloudapp.net/service/v1")]
- public interface ICloudIMService
- {
- [OperationContract]
- string Echo();
- }
- }
Code Snippet
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.Serialization;
- using System.ServiceModel;
- using System.Text;
- using CloudIM.ServiceContract;
-
- namespace CloudIM.WorkerRole
- {
- public class CloudIMService : ICloudIMService
- {
- public string Echo()
- {
- return "Hello, World";
- }
- }
- }
2. The App.config file:
Code Snippet
- <?xml version="1.0" encoding="utf-8" ?>
- <configuration>
- <appSettings>
- <add key="ServiceNamespace" value="cloudim" />
- <add key="ServiceIssuer" value="owner"/>
- <add key="ServiceSecret" value="***********************************"/>
- </appSettings>
- <system.diagnostics>
- <trace>
- <listeners>
- <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
- name="AzureDiagnostics">
- </add>
- </listeners>
- </trace>
- </system.diagnostics>
- <system.serviceModel>
- <services>
- <service name="CloudIM.WorkRole.CloudIMService">
- <endpoint binding="tcpRelayBinding" contract="CloudIM.WorkRole.ICloudIMService"></endpoint>
- </service>
- </services>
- </system.serviceModel>
- </configuration>
Then in WorkerRole.cs, host the service:
Code Snippet
- static void Main(string[] args)
- {
- // ...
-
- // create the service host reading the configuration
- ServiceHost host = new ServiceHost(typeof(CloudIMService), 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(sharedSecretServiceBusCredential);
- }
-
- host.Open();
-
- // ...
- }
Finally I deploy this package to the Windows Azure platform, but this service is not running.
Afterwards, I start troubleshooting – this could be as long as you think…
First, I doubt the “host” is not opened, but this one is quickly eliminated because no visible runtime exception shows after deployment; then, I try to create an Endpoint for this service using other protocols (http or https) but still failed to initialize after deploy. all the behaviors can work properly in my local development environment.
Finally I think it is the fault of the configuration, so I remove the <system.serviceModel> configuration from app.config, comment the host creation method, then deploy, good! it works now.
I think I have got something to solve this problem! by removing the WCF configuration section, take some change to the WorkerRole.cs, my service is finally running on the cloud. The main point is, do not use configuration to describe the WCF service contract and behavior, alternatively, programmatically create a service contract description and endpoint is the right way to make it work.
The worked version
1. The WorkerRole.cs:
2. App.config:
Code Snippet
- <?xml version="1.0" encoding="utf-8" ?>
- <configuration>
- <appSettings>
- <add key="ServiceNamespace" value="cloudim" />
- <add key="ServiceIssuer" value="owner"/>
- <add key="ServiceSecret" value="***************"/>
- </appSettings>
- <system.diagnostics>
- <trace>
- <listeners>
- <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
- name="AzureDiagnostics">
- </add>
- </listeners>
- </trace>
- </system.diagnostics>
- </configuration>
Here we go, the service status is now ready on the Windows Azure platform. :)
