Exposing Endpoints via WCF

Project Hosting
NuGet Package NServiceBus.Host (4.x)
Target NServiceBus Version: 4.x
Standard support for version 4.x of NServiceBus has expired. For more information see our Support Policy.

It is possible to "expose" the message send+receive action as a WCF service. This, in effect, allows a WCF service call to be "proxied" through to a message being sent, and then waiting for the response to return the WCF result.

When doing a blocking send+receive inside a WCF service, the service implementation is a client of the Callback Functionality.

Prerequisites for WCF functionality

The WCF functionality is part of the NServiceBus.Host NuGet package.

Expose a WCF service

To expose the endpoint as a WCF service, inherit from NServiceBus.WcfService<TRequest, TResponse>, as shown below. TRequest is the message type of the request. TResponse represents the result of processing the command and can be any type that is supported by the NServiceBus.Callback package.

Example:

public class CancelOrderService :
    WcfService<CancelOrder, ErrorCodes>
{
}

public class CancelOrderHandler :
    IHandleMessages<CancelOrder>
{
    IBus bus;

    public CancelOrderHandler(IBus bus)
    {
        this.bus = bus;
    }

    public void Handle(CancelOrder message)
    {
        // code to handle the message

        // return a status so that the WCF service has a return value
        bus.Return(ErrorCodes.Success);
    }
}

public enum ErrorCodes
{
    Success,
    Fail
}

public class CancelOrder :
    ICommand
{
    public int OrderId { get; set; }
}
In previous versions of the WCF support TResponse must be an enumerated type. To reply with enumeration types, the replying endpoint needs to reference NServiceBus.Callback and configure it accordingly.

Configure binding and address of WCF service

To expose the WCF service, change the configuration as shown below:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="Default">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <services>
    <service name="Server.WebServices.CancelOrderService"
             behaviorConfiguration="Default">
      <endpoint address="mex"
                binding="mexHttpBinding" 
                contract="IMetadataExchange" />
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:9009/services/cancelOrder" />
        </baseAddresses>
      </host>
    </service>
  </services>
</system.serviceModel>

The service name in <service name="XXX" needs to match the Type.FullName that derives from NServiceBus.WcfService<TRequest, TResponse>.

Queries and other return values

To allow clients to perform queries, it is best not to use NServiceBus. Messaging is designed for non-blocking operations, and queries are operations for which the user wishes to wait.

When performing operations that aren't straightforward as a simple query to return a value, for example a long calculation, consider invoking the operation locally where possible by referencing the DLL on the client.

Calling Web/WCF services

When invoke a Web/WCF service as a part of message handling logic, where that logic also updates transactional resources like a database, the best practice is to split it into two endpoints.

If no response is required from the Web/WCF service then instead use publish-subscribe. Have the first endpoint publish an event, to which the second endpoint subscribes, and have the second endpoint call the Web/WCF service.

If a response is required from the Web/WCF service, turn the first endpoint into a saga that sends (not publishes) a message to the second endpoint, which calls the Web/WCF service and replies with a response that is handled by the saga in the first endpoint.

Samples

Related Articles

  • Client side Callbacks
    The client (or sending process) has its own queue. When messages arrive in the queue, they are handled by a message handler.

Last modified