# Exposing Endpoints via WCF > [!WARNING] > **NServiceBus.WCF has been sunset and will be deprecated on April 16, 2031, in line with the end of [Extended Support](/nservicebus/upgrades/support-policy.md#extended-support) for NServiceBus 8. Support will end after the deprecation date** It is possible to expose the message send+receive action as a WCF service. In effect, this allows a WCF service call to be "proxied" through to a message being sent, and then wait for the response to return the WCF result. > [!NOTE] > When doing a blocking send+receive inside a WCF service, the service implementation is a client of the [callback functionality](/nservicebus/messaging/callbacks.md). ## Prerequisites for WCF functionality The WCF functionality is part of the [NServiceBus.Wcf NuGet package](https://www.nuget.org/packages/NServiceBus.Wcf). The package has a dependency to `NServiceBus.Callback`. The endpoint hosting the WCF services needs to configure the [callbacks accordingly](/nservicebus/messaging/callbacks.md). ## Expose a WCF service To expose the endpoint as a WCF service, inherit from `NServiceBus.WcfService`, 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: ```cs public class CancelOrderService : WcfService { } public class CancelOrderHandler : IHandleMessages { public Task Handle(CancelOrder message, IMessageHandlerContext context) { // code to handle the message // return a status so that the WCF service has a return value return context.Reply(ErrorCodes.Success); } } public enum ErrorCodes { Success, Fail } public class CancelOrder : ICommand { public int OrderId { get; set; } } ``` ## Configure binding and address of WCF service To expose the WCF service, change the configuration as shown below: ```xml ``` The service name in ``. ### OverrideBinding It is also possible to configure the binding and address in code for each service type individually: ```cs var wcfSettings = endpointConfiguration.Wcf(); wcfSettings.Binding( provider: serviceType => { if (serviceType == typeof(MyService)) { var binding = new NetNamedPipeBinding(); var address = new Uri("net.pipe://localhost/MyService"); return new BindingConfiguration(binding, address); } if (serviceType == typeof(CancelOrderService)) { var binding = new BasicHttpBinding(); var address = new Uri("http://localhost:9009/services/cancelOrder"); return new BindingConfiguration(binding, address); } return new BindingConfiguration(new BasicHttpBinding()); }); ``` The delegate is invoked for each service type discovered. The delegate needs to return a binding configuration which contains the binding instance to be used as well as optionally an absolute listening address. ### Int The integer response scenario allows any integer value to be returned in a strong typed manner. > [!NOTE] > The receiving endpoint requires a reference to `NServiceBus.Callbacks`. #### Expose service ```cs class MyService : WcfService { } ``` #### Response ```cs public class Handler : IHandleMessages { public Task Handle(Message message, IMessageHandlerContext context) { return context.Reply(10); } } ``` ### Enum The enum response scenario allows any enum value to be returned in a strong typed manner. > [!NOTE] > The receiving endpoint requires a reference to `NServiceBus.Callbacks`. #### Expose service ```cs class MyService : WcfService { } ``` #### Response ```cs public class Handler : IHandleMessages { public Task Handle(Message message, IMessageHandlerContext context) { return context.Reply(Status.OK); } } ``` ### Object The Object response scenario allows an object instance to be returned. > [!NOTE] > The receiving endpoint does not require a reference to `NServiceBus.Callbacks`. #### The Response message This feature leverages the message Reply mechanism of the bus and hence the response needs to be a message. ```cs public class ResponseMessage : IMessage { public string Property { get; set; } } ``` #### Expose service ```cs class MyService : WcfService { } ``` #### Response ```cs public class Handler : IHandleMessages { public Task Handle(Message message, IMessageHandlerContext context) { var responseMessage = new ResponseMessage { Property = "PropertyValue" }; return context.Reply(responseMessage); } } ``` ## Cancellation By default, a request is canceled after 60 seconds. It is possible to override the cancellation behavior with: ```cs var wcfSettings = endpointConfiguration.Wcf(); wcfSettings.CancelAfter( provider: serviceType => { return serviceType == typeof(MyService) ? TimeSpan.FromSeconds(5) : TimeSpan.FromSeconds(60); }); ``` The delegate is invoked for each service type discovered. The delegate needs to return a time span indicating how long a request can take until it gets canceled. ## Routing By default, a request is routed to the local endpoint instance. It is possible to override the routing behavior with: ```cs var wcfSettings = endpointConfiguration.Wcf(); wcfSettings.RouteWith( provider: serviceType => { if (serviceType == typeof(MyService)) { // route to fix remote destination return () => { var sendOptions = new SendOptions(); sendOptions.SetDestination("SomeDestination"); return sendOptions; }; } // route to this instance return () => { var sendOptions = new SendOptions(); sendOptions.RouteToThisInstance(); return sendOptions; }; }); ``` the replying endpoint handler: ```cs public class Handler : IHandleMessages { public Task Handle(Request message, IMessageHandlerContext context) { // Requires NServiceBus.Callbacks return context.Reply(new Response()); } } ``` The delegate is invoked for each service type discovered. The delegate needs to return a function delegate which creates a `SendOption` instance every time it is called. ## 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 usually must wait. When performing operations that aren't as 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 invoking 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 use [publish-subscribe](/nservicebus/messaging/publish-subscribe/index.md). 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](/nservicebus/sagas/index.md) that sends (_not_ publishes) a message to the second endpoint, which calls the Web/WCF service and [replies](/nservicebus/messaging/reply-to-a-message.md) with a response that is handled by the saga in the first endpoint.