Server Side Service Operations

This section describes service side service operations.

The following is the layout of a server side service operation

  • const WS_OPERATION_CONTEXT* context: The operation context.
  • Service Operations Parameters: Parameters pertaining to the service operation.
  • const WS_ASYNC_CONTEXT* asyncContext: Async context for executing the service operations asynchronously.
  • WS_ERROR* error: Rich error object.
HRESULT CALLBACK Add(const WS_OPERATION_CONTEXT* context, 
                     ULONG a, ULONG b, ULONG* result, 
                     const WS_ASYNC_CONTEXT* asyncContext, 
                     WS_ERROR* error)
{
    *result = a +b;
    return NOERROR;
}

Fault And Error Handling

The server side should use faults to deliver error conditions to the client. It can do so by returning a failing HRESULT and embedding the fault in the error object.

If the fault is not set on the error object and a failure HRESULT is returned, the infrastructure will attempt deliver a fault back to client. The level of details disclosed to the client in such a case is controlled by WS_SERVICE_PROPERTY_FAULT_DISCLOSURE service property on the Service Host.

Call Completion

A call on a synchronous server side service operation is said to be complete when either it has returned control back to the service host. For an asynchronous service operation a call is considered complete once the callback notification is issued by the service operation implementation.

Call Lifetime

Special care should be taken when implementing a server side service operation about its lifetime. The lifetime of a call can greatly affect how long the service host takes to shutdown.

If a server side service operation is expected to block because of some IO bound operation, it is recommended that it registers a cancellation callback such that it is notified if when service host is being aborted, or when the underlying connection is closed by the client.

Server side service operations and memory consideration

If a service operation needs to allocate memory for its outgoing parameters, it should use WS_HEAP object available to it through the WS_OPERATION_CONTEXT.

Example: Service Operation and WS_HEAP

HRESULT CALLBACK ProcessOrder (const WS_OPERATION_CONTEXT* context, const ULONG orderNumber, OrderReceipt** orderReceipt, const WS_ASYNC_CONTEXT* asyncContext, WS_ERROR* error)
{
    WS_HEAP* heap;
    HRESULT hr = WsGetOperationContextProperty (context, WS_OPERATION_CONTEXT_PROPERTY_HEAP, &heap, sizeof(heap), NULL, error);
    if (FAILED(hr))
        return hr;
    hr = WsAlloc(heap, sizeof (OrderReceipt), orderReceipt, error);
    if (FAILED(hr))
        return hr;
    hr = FillInReceipt(*orderReceipt);
    if (FAILED(hr))
        return hr;
    return NOERROR;
} 

Return Values

  • WS_S_ASYNC: Call will be completed async.
  • WS_S_END: Call completed successfully, the server is not expecting any WS_MESSAGE from the client beyond this call. If another WS_MESSAGE comes in then the server should abort the channel.
  • NOERROR/All other success HRESULTS: Call completed successfully. Note that it is recommended that the application should not return HRESULT other than NOERROR for successful completion of service operation.
  • Everything with a failure HRESULT: A fault is send back to the client if one is available in WS_ERROR. Otherwise a generic fault is send back to the client. See fault discussion above.

See, Call cancellation.