A Beginner’s Tutorial on Managing Sequence of Operations in WCF Service

In this article we will discuss about how we can enforce and manage sequencing operations in a WCF service. We will see how a WCF service can be configured to work in a way such that the call to methods in a WCF service always be in a specific order and calling the functions out of that order will result in exceptions.

Background

We have already seen how we can configure a WCF service instance as per our application needs (A Beginner’s Tutorial for Understanding WCF Instance Management [^]). Now in case we have configured our WCF service to work in a stateful mode by setting the InstanceContextModeto PerSession, one more question arises. The question is how can we configure the service in such a way that a particular order of operations in enforced on this stateful WCF service.

Why is this order important? The order is important because if our service is maintaining state for every client then perhaps we need to do some initialization of resource acquisitions whenever the instance is being created. The other functions of the service will then use these resources to perform their operations. We would also want to ensure the that our resource cleanup is done whenever a particular function is called (perhaps the last function in the sequence of functions).

Now we can very well define a convention that the clients should call some function first and then call the other functions of the service so that the initial function will take care of all initialization and the final function will take care of resource cleanup. But what if any client call some intermediate function without calling the initialization function or after calling the cleanup function? This could create some possible inconsistent behavior. WCF provide us a way to enforce this convention and make sure that if any client calls any function without calling the initialization function or after calling the cleanup function then the client call will fail.

Understanding the SessionMode property

before looking at the sequence specific configuration, let us understand a very important property called SessionMode. The SessionModeproperty goes as part of the ServiceContractattribute and it specifies how the service will implement sessions. SessionModecan be set to three possible values:

  1. Allowed
  2. NotAllowed
  3. Required

Allowedspecifies that the service will allow the sessions if the sessions are supported by the protocol being used i.e. binding and the InstanceContextModeis specified as PerSession.

NotAllowedspecifies that the service will not allow the sessions even if the sessions are supported by the binding and/or the InstanceContextModeis specified as PerSession.

Requiredoption specifies that the service will support sessions and the underlying binding/protocol should be chosen MUST support sessions.

Configuring the Sequence of Operations

As we have discussed above, if we need to enforce the order of operations in a WCF service, WCF provides a way to mark a particular function as the function that should be the first function to be called to initiate the instance creation process. This can be done by setting the IsInitiatingproperty of the OperationContractto true.

Similarly, to mark a function as the final function in a sequence of operations, we need to set the IsTerminating property of the OperationContractto true. The IsInitiating property for this function should be set to false.

Rest all the functions should be have the OperationContractwith the IsInitiatingproperty set to false. All these functions could only be called when the function marked with IsInitiatingtrue has been called and the function marked with IsTerminatingset to truehas not been called. Otherwise call to this function will result in an exception.

Using the code

Let us now create a sample service to see this in action.

Creating the Test Service

Let us create a simple service with three operations. There will be one function( Function1) that will initiate the instance creation, one function( Function3) that will terminate the instance. There will be one more function that could only be called only when Function1has been called and Function3has not yet been called. Calling this function otherwise would lead to an exception.

Also, Let us set the SessionModeproperty of the ServiceContractas SessionMode.Required so that this service could not be used in a session less scenario/binding. Let us look at the ServiceContractand OperationContactto achieve the same.

The service implementation will have the InstanceContextMode property of ServiceBehaviorset as InstanceContextMode.PerSession. The functions will simply return some dummy strings to show what method has been called. This will ensure that one instance of the service will be created for every client.

Creating a Host

Now since the ServiceContracthas the SessionModeproperty set to Required, we will have to choose the binding that supports sessions. So let us self host this service in a console application that will expose the service via TCP. Since netTcpBindingsupports sessions, hosting this service using this binding will supports sessions.

Details of the created endpoint is as follows:

  • Address: net.tcp://localhost/TestService
  • Binding: netTcpBinding
  • Contract: SampleServiceNamespace.SampleService

And the code to host the service will look like:

We can run the host to access our test service. Running the host will look like:

Host

Note: Please refer to the app.config file of the host application to see the full configuration.

Test Client and testing sequence of operations

We will now create a simple test client that will call the WCF service functions. First let us try to call the Function2directly. Now since the Function1is marked as IsInitiating=true, direct call to Function2will result in an exception.

function2Before

Same will be the case if we try to call Function3, since Function3is marked as IsTerminating=true, calling this without calling Function1will also result in exception.

Function3

Now let us try the valid sequence of operations. We will call Function1(which is marked as IsInitiating=true) then we will call Function2(which is supposed to be called after Function1and before Function3) and finally we will call Function 3(which is marked as IsTerminating=false.

proper

And now finally, let us try to call Function2after call to Function3has been completed. Since Function3has been marked as IsTerminating=true, call to Function2after this will result in exception.

Function2After

And thus by setting the IsInitatingand IsTerminating property we have enforced as sequence of operations in our WCF service.

A Note on Durable WCF Services

WCF also provides a option for marking the service as Durable service. A durable service is a service that persist the information of client sessions in some permanent stores like databases so that even in case of service class instance goes off, it could regain the state information once a new instance for the same client comes up. This is very useful when we need a stateful service running for a long time.

A service can be marked as DurableServiceto make it a durable service. The functions should also be marked as DurableOperationto make it a durable operation. The DurableOperation supports the similar kind of properties to maintain order of operations. For a durable operation, setting the CanCreateInstanceto true will make the operation as the first operation in the sequence and setting the CompleteInstanceto true will make the operation as terminating operation in in sequence.

Note: This is a very high level overview of durable services. Durable service creation requires some more configuration to be done at service end.

Point of interest

In this article we saw how we can enforce an order/sequence of operations in a stateful WCF service. This has been written from a beginner’s perspective(but some knowledge of WCF service and instance modes is required). I hope this has been informative.

Download sample code for this article: WCFSequencingSample