Notes about Hosting WCF services on Worker Roles
WCF services works great on IIS. This is why I love to use Web role to host WCF services. This is the recommendation I give to my customers – Use IIS whenever possible to host your services. Yet there are scenarios where IIS does not fit. For example a scheduling might not work on IIS because of it's recycling model. In such cases it is required to host the service on a Worker Role.
When hosting WCF service service on a worker role there are few points to remember:
1. It is required to open an input (external) endpoint using VS role properties tabs or directly in the role definition file. It is recommended to explicitly specify the external and internal port (let them be the same port for simplicity)

2. Specify your domain as a setting for implementation of the external endpoint.

3. Write the code that open the WCF service host. Do not put it in the OnStart method ! because if it fails your role will not start and you will not be able to connect (remote desktop) to identify the problem. Put the code in the beginning of the Run Method.
Unlike traditional service host here there are two endpoints to handle
1: endpointurl - The external endpoint to which you call from the outside world (out side the Load balancer of the data center)
2: listenurl - The internal endpoint within the data center.
public ServiceHost m_serviceHost;
public override void Run()
{
try
{
//Hosting the WCF runtime service
if (m_serviceHost != null)
{
m_serviceHost.Close();
}
// define an external endpoint for client traffic
RoleInstanceEndpoint externalEndPoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["CalcEP"];
RoleInstanceEndpoint mexEndPoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["MexEP"];
var binding = new BasicHttpBinding("Calc.BasicHTTPBinding");
//Add a an endpoint for the service
string listenurl = string.Format("http://{0}/CalcService", externalEndPoint.IPEndpoint);
string endpointurl = string.Format("http://{0}:{1}/CalcService",
RoleEnvironment.GetConfigurationSettingValue("Domain"),
externalEndPoint.IPEndpoint.Port);
// Create a ServiceHost for the CalculatorService type and provide the base address.
m_serviceHost = new ServiceHost(typeof(WCFCalc), new Uri(endpointurl));
m_serviceHost.AddServiceEndpoint(typeof(ICalc), binding, endpointurl, new Uri(listenurl));
//Add a metadata endpoint. Client should use this port to request metadata.
Binding mexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
string mexlistenurl = string.Format("http://{0}/CalcService", mexEndPoint.IPEndpoint);
string mexendpointurl = string.Format("http://{0}:{1}/CalcService",
RoleEnvironment.GetConfigurationSettingValue("Domain"), mexEndPoint.IPEndpoint.Port);
m_serviceHost.AddServiceEndpoint(typeof(IMetadataExchange),
mexBinding, mexendpointurl, new Uri(mexlistenurl));
// Open the ServiceHostBase to create listeners and start listening for messages.
m_serviceHost.Open();
}
catch (Exception ex)
{
//Use some kind of logging...
File.WriteAllText("log.txt", ex.ToString());
}
// let the worker role run...
while (true)
{
Thread.Sleep(10000);
}
}
4. set the binding hostNameComarisoneMode to be exact.
<bindings>
<basicHttpBinding>
<binding name="Calc.BasicHTTPBinding"
hostNameComparisonMode="Exact">
</binding>
</basicHttpBinding>
</bindings>
The root cause of this is that Azure creates an “IP-bound Weak Wildcard” HTTP reservation using the IP address of the modeled endpoint. But by default, WCF attempts to bind to the “Strong Wildcard”, leading to a reservation problem which will cause the exception "AddressAccessDeniedException: HTTP could not register URL http://+:8000/<…>." to be thrown. The WCF binding must be compatible with the reservation. Currently, the only known way is to use the Exact hostname comparison mode.
5. Log exceptions.
Use Azure diagnostics and or Remote Desktop to gain access to these logs.
That is it.
Enjoy
Manu