Consideration when hosting WCF ServiceHost in WebRole using Internal Azure Endpoints

Author by Eric Franz

When hosting a WCF service via a ServiceHost, it’s important to instantiate your ServiceHost at the right time. If you instantiate your ServiceHost during your WebRole.OnStart() method it will work, but you may have issues down the road. The WebRole.OnStart() method runs in a different process than your WebRole’s site. To see this in action just put a breakpoint in WebRole.OnStart() and Global.asax Application_Start() then check System.Diagnostics.Process.GetCurrentProcess().Id, you’ll see that it’s a different value.

public class WebRole : RoleEntryPoint { public override bool OnStart() { // Put a breakpoint below and type ?System.Diagnostics.Process.GetCurrentProcess().Id in the immediate window return base.OnStart();
....................................
public class Global : System.Web.HttpApplication { void Application_Start(object sender, EventArgs e) { // Put a breakpoint above and type ?System.Diagnostics.Process.GetCurrentProcess().Id in the immediate window

The WebRole.OnStart() method actually runs in a process called WaIISHost.exe. Because of this, if you instantiate your ServiceHost in OnStart() any code which executes inside your WCF Service (eg your [ServiceContract] implementation) will not have access to the web.config because it will be hosted from the WaIISHost process. In addition, because your code is running in another process, I would expect Fusion to have issues with assembly resolution in some cases, and also non-fully qualified File.Open() calls. In prior versions of the Azure SDK you could create a duplicate of your configuration in a file named WaIISHost.exe.config and set it to always copy to the output directory to at least get app config values read correctly by System.Configuration.ConfigurationManager. I’ve also heard the 1.8 Azure SDK can support an app.config in your web role. However, this is not ideal as you can have redundant configuration maintenance across code running in each process. In the case of your own service you may be able to use ConfigurationChannelFactory and inject your own configuration values the service needs; but what about any third party code your service may be hosting? Who knows what dependencies they may have?

A real world case where you can have a problem resulting from starting your ServiceHost in OnStart() can be seen with Windows Azure Caching. Your WCF service can run fine all day until you instantiate a DataCache object. Upon doing this you’ll receive an error such as:

ErrorCode:SubStatus:Server collection cannot be empty.

This is because the Windows Azure Caching code inside Microsoft.ApplicationServer.Caching.Client.dll is trying to read cache configuration values from a web.config it cannot find.

SOLUTION:

The solution to reliably serve your WCF service in your WebRole is to move your ServiceHost instantiation and reference to Global.asax Application_Start(). Once you do this, your ServiceHost will now be running in the correct process "3wp" any configuration file dependencies will then be resolved.

Author

Eric Franz

Modern Applications Solution Lead