Sequencing Operations in a WCF Service


When using the PerSession instance context mode, it is often useful to be able to control the order in which a client application invokes operations in a WCF service. Revisiting the ShoppingCartService service, suppose that you decide to use the PerSession instance context mode rather than PerCall. In this scenario, it might not make sense to allow the client application to remove an item from the shopping cart, query the contents of the shopping cart, or perform a checkout operation, if the user has not actually added any items to the shopping cart. Equally, it would be questionable practice to allow the user to add an item to the shopping cart after the user has already checked out and paid for the items in the cart. There is actually a simple sequence to the operations in the ShoppingCartService service, and the service should enforce this sequence:

  1. Add an item to the shopping cart.

  2. Add another item, remove an item, or query the contents of the shopping cart.

  3. Check out and empty the shopping cart.

When you define an operation in a service contract, the OperationContract attribute provides two Boolean properties that you can use to control the order of operations and the consequent lifetime of the service instance:

  • IsInitiating. If you set this property to true, a client operation can invoke this operation to initiate a new session and create a new service instance. If a session already exists, then this property has no further effect. By default, this property is set to true. If you set this property to false, then a client application cannot invoke this operation until another operation has initiated the session and created a service instance. At least one operation in a service contract must have this property set to true.

  • IsTerminating. If you set this property to true, the WCF runtime will terminate the session and release the service instance when the operation completes. The client application must create a new connection to the service before invoking another operation, which must have the IsInitiating property set to true. The default value for this property is false. If no operations in a service contract specify a value of true for this property, the session remains active until the client application closes the connection to the service.

Note 

These properties are specific to WCF, and do not conform to any current WS-* standards. Using them can impact the interoperability of your service with client applications created by using other technologies.

The WCF runtime checks the values of these properties for consistency at runtime in conjunction with another property for the service contract called SessionMode. The SessionMode property of the service contract specifies whether the service supports reliable sessions. If you specify a value of false for the IsInitiating property of any operation, then you must set the SessionMode property of the service contract to SessionMode.Required, otherwise the WCF runtime will throw an exception. Similarly, you can only set the IsTerminating property to true if the SessionMode property of the service is set to SessionMode.Required.

More Info 

You will learn more about the SessionMode property of a service contract, and reliable sessions, in Chapter 9, “Implementing Reliable Sessions.”

In the final set of exercises in this chapter, you will see how to apply the IsInitiating and IsTerminating properties of the OperationBehavior attribute.

Control the sequence of operations in the ShoppingCartService service

  1. In Visual Studio 2005, edit the image from book ShoppingCartService.cs file in theShoppingCartService project.

  2. Add the SessionMode property to the ServiceContract attribute for the IShoppingCartService interface, as shown in bold below:

     [ServiceContract(SessionMode = SessionMode.Required,                  Namespace = "http://adventure-works.com/2007/03/01",                  Name = "ShoppingCartService")] public interface IShoppingCartService {      }

  3. Modify the operations in the IProductsService interface by specifying which operations initiate a session and which operations cause a session to terminate, as follows:

     public interface IShoppingCartService {     [OperationContract(Name="AddItemToCart", IsInitiating = true)]     bool AddItemToCart(string productNumber);     [OperationContract(Name = "RemoveItemFromCart", IsInitiating = false)]     bool RemoveItemFromCart(string productNumber);     [OperationContract(Name = "GetShoppingCart", IsInitiating = false)]     string GetShoppingCart();     [OperationContract(Name = "Checkout", IsInitiating = false,                                           IsTerminating = true)]     bool Checkout(); }

  4. Change the InstanceContextMode property of the service to create a new instance of the service for each session:

     [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class ShoppingCartServiceImpl : IShoppingCartService {      }

  5. In the AddItemToCart method, comment out the single statement that calls the restoreShoppingCart method and the two statements that call the saveShoppingCart method.

    The service is using the PerSession instance context mode, so the session will maintain its own copy of the user’s shopping cart in memory; these method calls are now unnecessary.

  6. In the RemoveItemFromCart method, comment out the statement that calls the restoreShoppingCart method and the statement that calls the saveShoppingCart method.

  7. In the GetShoppingCart method, comment out the statement that calls the restoreShoppingCart method.

You can test the effects of these changes by modifying the client application.

Test the operation sequencing in the ShoppingCartService service

  1. Edit the image from book ShoppingCartServiceProxy.cs file in the ShoppingCartClient project. This is the proxy class that you generated earlier. You have modified the service contract, so you must update this class to reflect these changes. You can use the svcutil utility to generate a new version of the proxy, but the changes are quite small so it is easier to add them by hand:

    • Modify the ServiceContract attribute for the ShoppingCartService interface and specify the SessionMode property:

       [System.ServiceModel.ServiceContractAttribute(SessionMode=System.ServiceModel.Ses sionMode.Required, Namespace="", )]

    • Add the IsInitiating property to the OperationContract attribute of the AddItemToCart, RemoveItemFromCart, and GetShoppingCart methods:

       [System.ServiceModel.OperationContractAttribute(IsInitiating = true, Action="")] bool AddItemToCart(string productNumber); [System.ServiceModel.OperationContractAttribute(IsInitiating = false, Action=" " )] bool RemoveItemFromCart(string productNumber); [System.ServiceModel.OperationContractAttribute(IsInitiating = false, Action="") ] string GetShoppingCart();

    • Add the IsInitiating property and the IsTerminating property to the OperationContract attribute of the Checkout method:

       [System.ServiceModel.OperationContractAttribute(IsInitiating = false, IsTerminating = true, Action="")] bool Checkout();

  1. Edit the image from book Program.cs file in the ShoppingCartClient project. Add the statements shown below in bold between the code that displays the shopping cart and the code that closes the proxy:

     … // Query the shopping cart and display the result string cartContents = proxy.GetShoppingCart(); Console.WriteLine(cartContents); // Buy the goods in the shopping cart proxy.Checkout(); Console.WriteLine("Goods purchased"); // Go on another shopping expedition and buy more goods // Add a road seat assembly to the shopping cart proxy.AddItemToCart("SA-R127"); // Add a touring seat assembly to the shopping cart proxy.AddItemToCart("SA-T872"); // Remove the road seat assembly proxy.RemoveItemFromCart("SA-R127"); // Display the shopping basket cartContents = proxy.GetShoppingCart(); Console.WriteLine(cartContents); // Buy these goods as well proxy.Checkout(); Console.WriteLine("Goods purchased"); // Disconnect from the ShoppingCartService service proxy.Close();  

    The first statement that invokes the Checkout operation terminates the session and destroys the shopping cart. The statements that follow therefore require a new session, with its own shopping cart.

  2. Start the solution without debugging. In the ShoppingCartClient console window, press Enter.

    The client application adds the three items to the shopping cart and outputs the contents. It then displays an error:

    image from book

    This demonstrates that the Checkout method successfully terminated the session. The service has closed the channel that the client application was using when the session finished. The client application must create a new channel before it can communicate with the service again.

  3. Press Enter to close the client application console window. In the host application console window, press Enter to stop the service.

  4. The simplest way to create a new connection is to rebuild the proxy. However, you must ensure that you provide the user’s credentials again, as these will be lost when the new instance of the proxy is created.

    In Visual Studio 2005, add the following statements after the code that performs the Checkout operation in the Main method of the Program class in the ShoppingCartService project:

     … // Buy the goods in the shopping cart proxy.Checkout(); Console.WriteLine("Goods purchased"); // Go an another shopping expedition and buy more goods proxy = new ShoppingCartServiceClient("HttpBinding_ShoppingCartService"); // Provide credentials to identify the user proxy.ClientCredentials.Windows.ClientCredential.Domain = "LON-DEV-01"; proxy.ClientCredentials.Windows.ClientCredential.UserName = "Fred"; proxy.ClientCredentials.Windows.ClientCredential.Password = "Pa$$w0rd"; // Add a road seat assembly to the shopping cart proxy.AddItemToCart("SA-R127");  

  5. Start the solution again. In the ShoppingCartClient console window, press Enter.

    The client application successfully creates a second session after terminating the first. The second session has its own shopping cart:

    image from book

  6. Press Enter to close the client application console window. In the host application console window, press Enter to stop the service.

As an additional exercise, you can test the effects of invoking the RemoveItemFromCart, GetShoppingCart, or Checkout operations without calling AddItemToCart first. These operations do not create a new session, and the client application should fail, with the exception shown in Figure 7-1.

image from book
Figure 7-1: Invoking operations in the wrong sequence.




Microsoft Windows Communication Foundation Step by Step
Microsoft Windows Communication Foundation Step by Step (Step By Step Developer Series)
ISBN: 0735623368
EAN: 2147483647
Year: 2007
Pages: 105
Authors: John Sharp

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net