0
votes

I've set up a basic Service Fabric solution with a stateless service and Web API and tested that everything works using the default service remoting listener. Happy days!

When I try to replace the default listener with a service bus relay (how I intend to communicate with the service) I'm getting errors at startup.

CreateServiceInstanceListeners()

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new[] { 
        new ServiceInstanceListener(context => {
            var wcfRelay = new WcfCommunicationListener<ICommercial>(
                wcfServiceObject: this,
                serviceContext: context,
                endpointResourceName: "serviceRelay");

            return wcfRelay;
        })
    };
}

Service config (app.config)

  <system.serviceModel>
    <extensions>…</extensions>
    <services>
      <service name="Commercial.Service.CommercialService">
        <endpoint address="http://[namespace].servicebus.windows.net/CommercialService" 
                  name="serviceRelay" 
                  binding="basicHttpRelayBinding" 
                  contract="Commercial.Interface.ICommercial" 
                  behaviorConfiguration="relayToken" />
      </service>
    </services>
    <bindings>
      <basicHttpRelayBinding>
        <binding closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" maxBufferSize="5886800" maxBufferPoolSize="524288" maxReceivedMessageSize="5886800" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="5886800" maxArrayLength="5886800" maxBytesPerRead="5886800" maxNameTableCharCount="16384" />
        </binding>
      </basicHttpRelayBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="relayToken">
          <transportClientEndpointBehavior>
            <tokenProvider>
              <sharedAccessSignature keyName="RootManageSharedAccessKey" key="[key]" />
            </tokenProvider>
          </transportClientEndpointBehavior>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>

If I break in the listener creation I see it's creating two service endpoints:

enter image description here

And eventually I get this error showing up for each node in Service Fabric Explorer.

Unhealthy event: SourceId='System.RA', Property='ReplicaOpenStatus', HealthState='Warning', ConsiderWarningAsError=false. Replica had multiple failures in_Node_1 API call: IStatelessServiceInstance.Open(); Error = System.InvalidOperationException (-2146233079) The Service contains multiple ServiceEndpoints with different ContractDescriptions which each have Name='ICommercial' and Namespace='http://[schema_path]/20170713'. Either provide ContractDescriptions with unique Name and Namespaces, or ensure the ServiceEndpoints have the same ContractDescription instance. at System.ServiceModel.Dispatcher.UniqueContractNameValidationBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase) at System.ServiceModel.Description.DispatcherBuilder.ValidateDescription(ServiceDescription description, ServiceHostBase serviceHost) at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) at System.ServiceModel.ServiceHostBase.InitializeRuntime() at System.ServiceModel.ServiceHostBase.OnBeginOpen(TimeSpan timeout, AsyncCallback callback, Object state) at System.ServiceModel.Channels.CommunicationObject.OpenAsyncResult.InvokeOpen() at System.ServiceModel.Channels.CommunicationObject.OpenAsyncResult..ctor(CommunicationObject communicationObject, TimeSpan timeout, AsyncCallback callback, Object state) at System.ServiceModel.Channels.CommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, Object state) at Microsoft.ServiceFabric.Services.Communication.Wcf.Runtime.WcfCommunicationListener`1.Microsoft.ServiceFabric.Services.Communication.Runtime.ICommunicationListener.OpenAsync(CancellationToken cancellationToken) at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.d__20.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.d__14.MoveNext()

I'm not exactly clear how to remedy this "Either provide ContractDescriptions with unique Name and Namespaces, or ensure the ServiceEndpoints have the same ContractDescription instance".

1

1 Answers

0
votes

The endpointResourceName should definitely point to the endpoint that you have specified within your ServiceManifest file. Anyway I'm not even sure that app.config will even work here... Have you seen any SF example with WCF listener that uses app.confing? Check out this nice example to configure the required settings in code - ServiceFabric.WcfCalc. Hopefully it will help.