Search code examples
azure-service-fabric

Publicly exposing a WCF restful service via http from Service Fabric


I am trying to expose a WCF based restful service via http and am so far unsuccessful. I'm trying on my local machine first so prove it works. I found a suggestion here that I remove my local cluster and then manually run this powershell command from the SF SDK folder as administrator to recreate it with the machine name binding: .\DevClusterSetup.ps1 -UseMachineName

It created the cluster successfully. I can use the SF Explorer and see in the cluster manifest that entries in the NodeList show the machine name rather than localhost. This seems good.

But the first problem I notice is that if I expand my way through SF Explorer down to the node my app is running on I see an endpoints entry but the URL is not what I'd expect. I am seeing this: http://surfacelap/d5be9425-3247-4290-b77f-1a90f728fb8d/39cda0f7-cef4-4c7f-8af2-d05786a834b0-131111019607641260

Is that what I should see even though I have an endpoint setup? I did not expect the guid and other numbers in the path. This makes me suspect that SF is not seeing my service as being publicly accessible and instead is maybe only setup for internal access within the app? If I dig down into my service manifest I see this as expected:

<Resources>
    <Endpoints>
      <Endpoint Name="ResolverEndpoint" Protocol="http" Type="Input" Port="80" />
    </Endpoints>
</Resources>

But how do I know if the service itself is mapped to it? When I use the crazy long url above and try a simple method of my service I get an http 202 response and no response data as expected. If I then change the method name to one that doesn't exist I get the same thing, not the expected http 404. I've tried using both my machine name and localhost. Same result.

So clearly I'm doing something wrong. Below is my CreateServiceInstanceListeners override. In it you can see I use "ResolverEndpoint" as my endpoint resource name, which matches the service manifest:

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new[] { new ServiceInstanceListener((context) =>
            new WcfCommunicationListener<IResolverV2>(
                serviceContext: context,
                wcfServiceObject: new ResolverServiceV2(),
                listenerBinding: new WebHttpBinding(WebHttpSecurityMode.None),
                endpointResourceName: "ResolverEndpoint"
            )
        )};
    }

What am I doing wrong here?


Solution

  • Here's a way to get it to work: https://github.com/loekd/ServiceFabric.WcfCalc

    Essential changes to your code are the use of the public name of your cluster as endpoint URL and an additional WebHttpBehavior behavior on that endpoint.