views:

571

answers:

1

I'm currently implementing a WCF REST service on a web role in Windows Azure, and I'm trying to add some communication between the instances of the role so that they can keep each other updated when, say, some data is updated in blob storage. What I'd like to do is host the same WCF service on both the external and internal HTTP endpoints of the web role. However, from what I've read, WCF is limited to just one base address per protocol when hosted in IIS. When I enable the internal HTTP endpoint for my role and try to start up my service using the WebServiceHostFactory, this is the error I get:

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.

Parameter name: item

I've Googled around a bit, and the one workaround I've seen in various places suggests adding a baseAddressPrefixFilter in the web.config. However, if I don't know the full URL for either endpoint before I run the app, I'm not sure how to get that to work.

Alternatively, this issue seems constrained to just IIS hosting, so is there some other hosting method I could use in Azure that would work? I would think self-hosting outside of any IIS context or whatever wouldn't be robust/secure enough, but I don't know for sure.

Does anyone know how to get around this issue? It seems like it would be a pretty common thing to want to host a web service on both endpoints of a web role. I'm relatively new to WCF, so there may be something obvious I'm missing. Any help is appreciated.

A: 

I finally figured this out on Friday. I'll try and give a more detailed answer and/or blog about this later, but for now, here's a summary of the solution I came up with:

  • I don't have a system.serviceModel section in the web.config file at all. There may be some parts of this you can configure through the web.config, but doing it all in code was just easier for me.
  • Each endpoint has to be on its own service. When both endpoints are using the same protocol (HTTP, in this case) and you're trying to host on IIS, there's really no easy way around this.
  • Each service has to have its own .svc file. I've heard that supposedly a .svc file isn't necessary for hosting in IIS, but if that's true, I haven't seen any other way to make it work.
  • Each service also has its own custom service host factory. In the factory, when creating the host, I used the base address parameter whose port matched up to the endpoint I wanted to use. I'm told this base address doesn't actually matter, but I can't vouch for that myself. Then when creating the endpoint, just use an empty string for the endpoint address.
  • Since I wanted to make a REST service, I would usually use WebServiceHost, but that was causing some various problems, so I just used ServiceHost instead and added the WebHttpBinding and WebHttpBehavior to the endpoint manually.
  • Finally, when calling the internal service from the external one, I had to make sure to surround the call with a new operation context scope, like so:

using (new OperationContextScope((IContextChannel)myClientFromChannelFactory))
{
    myClientFromChannelFactory.MyServiceMethod();
}

I asked a similar question on the MSDN Windows Azure forums and got some of the information there, so there may be some more helpful info there.

Hope that helps anyone else out there who runs into the same issue.

Jonathan Schuster