Managing State and Service Instances in a WCF service – The case of a ShoppingCart : Part 1

We have seen in previous posts how to host and consume WCF services where the client used to invoke some operations of the service. These operations though, were totally independent and no state was needed to be kept. The client invokes the desired operation, for example GetProduct, and the service just returns the result back to him. If client decide to call one more time the same operation, the first one will have no impact on the second one. Consider though, the case of an e-shop website, where users add items to cart via a webservice, calling an “AddToCart” operation several times. When the user decides to check out he wants to see what items were added to cart. So how can this be implemented? Who’s side is the one who keeps state of what items are being added to cart? Who keeps the state of the cart? The answer is that both client and the WCF service can maintain user’s data during a session. The client could store information using cookies but this raise security issues. We are going to see how the WCF service can maintain the shopping cart contents through a structure.

Start by creating a blank solution and add a WCF Service library named “ShoppingCartService”. Rename the IService.cs and Service.cs file to IShoppingCartService.cs and ShoppingCartService.cs respectively. This will be our service project which will support operations such as “AddItemToCart” or “RemoveItemToCart”. We ‘ll also need access the AdventureWork database so create an EntityModel pointing to that database, and add the Product and ProductInventory tables to it. Creating EntityModel is out of scope of this post and I assume you know how to do it. Below you will find the code both for IShoppingCartService.cs and ShoppingCartService.cs files.

You will notice that the service make use of a structure “ShoppingCartItem” for every item the user wants to add to the cart. Every instance of the service is assigned a list of “ShoppingCartItem” so when the user adds items, these are added to the list. When the user wants to remove an item, this item is removed from the pre-mentioned list. The all functionality is simple. To add an item, we first retrieve it from the database passing the ProductNumber as a parameter and then create a new instance of ShoppingCartItem, assigning the values just retrieved from database. Build the solution and continue by creating a new project in the solution. This will be our host project, a console C# application, named “ShoppingCartHost”. Right click the new project and add references to the “ShoppingCartService” project plus the System.ServiceModel and System.Data.Entity assemblies. Configure the App.config file to host the service as follow. Be careful to modify the “connectionStrings” element due to yours implementation.

Notice that the service will be host by the console application at the http://localhost:9000/ShoppingCartService/ShoppingCartService.svc address. In order for the client application to use that http port you need first to reserve it. Run the following command in the “Developer Command Promt for VS2012”, which relies under the Developer Tools folder inside the Visual Studio 2012 folder. Make sure you enter your username.

netsh http add urlacl url=http://+:9000/ user=UserName

Modify the Program.cs file of the host Console application to start the service when it runs.

Next, add a new Console application which will be our client. Name it “ShoppingCartClient” (weird ah?). We need to add a proxy class which will be able to call the service operations. Also we need to configure the App.config file and add the right endpoint. For the proxy class, open again the “Developer Command Promt for VS2012”, navigate to the Service’s project /bin/debug folder and run the following commands.

The ShoppingCartServiceProcy.cs file created will be our proxy implementation. Simply copy and paste in your client project.

Following edit the App.config of the client’s project and add some code to the Main method, to actually call the service, add three items and then display them from the Shopping Cart. Make sure you have added a System.ServiceModel reference to the client project.

That’s it. Right click the solution and select Start up projects. Choose the host and the client projects and set as Action Start. Build the solution and Run Without Debugging. Press enter on the client console application and you will see that items actually were added to the Cart and then retrieved back.

Notice that the first two items, added with the same ProductNumber, that is the user want to buy two of them. So, since at the second call, the particular item were already on the cart, the volume was just increased by one. But what if one other client, consume the same service at the same time and add the same item? Was he going to order 3 Items instead of one? We are going to answer that in later post where we are going to continue the discussion on how to manage State and Instances of a WCF service

4 replies

Hello I am refreshing my knowledge of WCF lately and have really enjoyed your posts! One question though – aren’t services by default going to lose your shoppingCart List? Don’t you need some sort of service attribute to maintain state between calls, or is this a feature specific to the ws2007HttpBinding you’ve specified? Thanks!

Very good question actually. For now just keep this in mind: The service with the above simple implementation creates an instance of a ShoppingCart list (private instance variable) when an instance of the service is itself created by the host. This instance is only destroyed after the client closes the connection which means that it can hang around between calls (from same client). If another client application calls the WCF service, by default a new Service instance will be created and will maintain a new shoppingCart list for serving that client. But this is configurable. As you mentioned you can use specific attributes to manage instances and state, for example you could use only one instance of the service for managing all client requests or create a new instance every time an operation of the service was consumed. We are going to see how these work in another post, as soon as possible i hope!

The purpose of this blog is to broaden my education, promote experimentation and enhance my professional development. Albert Einstein once said that “If you can’t explain it simply, you don’t understand it well enough” and I strongly believe him!