Click here to Skip to main content
Click here to Skip to main content

Using Session State in a Web Service

, 11 May 2009
Rate this:
Please Sign up or sign in to vote.
Usually, when you think of a Web Service, you think …make the call, get the response, and get on with the task at hand. These "one shot" calls are the norm in Web Services but there may be times when you need a little more. You may need the Web Service to remember states between calls. As an exampl
Prize winner in Competition "Smart Client Article Contest"

Usually, when you think of a Web Service, you think …make the call, get the response, and get on with the task at hand. These "one shot" calls are the norm in Web Services but there may be times when you need a little more. You may need the Web Service to remember states between calls.

As an example, I wrote a Web Service that had to perform a lengthy operation. I didn't want to lock up the client by making a synchronous call, so once the job was started, the call returned. Every few seconds, on a timer, the client would call a GetStatus function in the Web Service to get the status of the running job. When the status was retrieved, a progress bar on the client was updated. It worked well.

There is support for using Session State in Web Services but it doesn't work "out-of-the-box".

This article assumes you know how to create and call a Web Service.

First we need a Web Service. I created a basic Web Service and then modified the supplied HelloWorld function that is created by default:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
 
namespace DemoWebService
{
    [WebService(Namespace = "http://AcmeWidgets.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
 
    public class MyDemo : System.Web.Services.WebService
    {
        [WebMethod (EnableSession = true)]
        public string HelloWorld()
        {
            // get the Count out of Session State
            int? Count = (int?)Session["Count"];
 
            if (Count == null)
                Count = 0;
 
            // increment and store the count
            Count++;
            Session["Count"] = Count;
 
            return "Hello World - Call Number: " + Count.ToString();
        }
    }
}

Note: The key thing to do is add (EnableSession = True) to the WebMethod tag. The rest of the code simply keeps track of how many times each client has called the Web Service method.

Side Note: I am using a Nullable Type to simplify the retrieving of Count from the Session collection.

Here's the old school way:

int Count;

if (Session["Count"] == null)
    Count = 0;
else
    Count = (int)Session["Count"];

Here's the new school way...Nullable Type...is better, yah?

int? Count = (int?)Session["Count"];

if (Count == null)
    Count = 0;

Ok, now the client. You've built the Web Service. You've added the Web Service to the client project (right-click the project and select "Add Web Reference…"). A proxy class has been created.

In a button click event, we instantiate the proxy class, call our function and update a label. This is going to be great…it's going to be so easy…

protected void Button1_Click(object sender, EventArgs e)
{
    // instantiate the proxy and call our function
    localhost.MyDemo MyService = new localhost.MyDemo();

    Label1.Text += MyService.HelloWorld() + "<br />";
}

We click the button a few times, but instead counting, we get this:

Hello World - Call Number: 1
Hello World - Call Number: 1
Hello World - Call Number: 1

Explanation: When an object is put into the Session collection, Asp.Net gives the caller an indentifying cookie behind the scenes…the SessionID. This is like when you check your coat at an expensive restaurant (I've heard) and you get a coat check ticket. When you go to get your coat back, you must have the ticket. So why isn't the proxy storing the SessionID as a cookie?

Key Point: The proxy generated doesn't have a CookieContainer.

Solution: Create a CookieContainer in the proxy (it already has a reference for it)

Here's the modified code:

protected void Button1_Click(object sender, EventArgs e)
{
    // instantiate the proxy 
    localhost.MyDemo MyService = new localhost.MyDemo();

    // create a container for the SessionID cookie
    MyService.CookieContainer = new CookieContainer();
 
    // call the Web Service function
    Label1.Text += MyService.HelloWorld() + "<br />";
}

All right, problem solved. This is great…it's going to be so easy… Fire up the web page, click the button a few times, and…

Hello World - Call Number: 1
Hello World - Call Number: 1
Hello World - Call Number: 1

@#%* Why does life have to be so hard?

Explanation: When the proxy went out of scope, it was uninstantiated and ceased to exist. The CookieContainer also ceased to exist. And our cookie, the SessionID…a.k.a. coat check ticket…was lost.

Key Point: The proxy has to remain in existence between calls to the Web Service.

Solution: Keep the proxy around. In a Windows Forms application this is easy. Make the proxy global or static…just don't put it on the stack. For a Web Application it's a bit trickier, we put the proxy into the Session collection.

protected void Button1_Click(object sender, EventArgs e)
{
    localhost.MyDemo MyService;

    // try to get the proxy from Session state
    MyService = Session["MyService"] as localhost.MyDemo;

    if (MyService == null)
    {
        // create the proxy
        MyService = new localhost.MyDemo();
 
        // create a container for the SessionID cookie
        MyService.CookieContainer = new CookieContainer();
 
        // store it in Session for next usage
        Session["MyService"] = MyService;
    }

    // call the Web Service function
    Label1.Text += MyService.HelloWorld() + "<br />";
}

All right, we hope the problem is solved because this is getting tiring. Fire up the web page, click the button a few times and…

Hello World - Call Number: 1
Hello World - Call Number: 2
Hello World - Call Number: 3

Ah, the sweet bliss of working code.

I hope you found this informative and helpful.

Steve Wellens

[Update:]

If you use "Add Web Service" instead of "Add Web Reference" in VS2008, the proxy generated works with out any fooling around. However, the proxy can only be consumed by .Net 3.0 and higher applications.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Steve Wellens
EndWell Software, Inc.
United States United States
I am an independent contractor/consultant working in the Twin Cities area in Minnesota. I work in .Net, Asp.Net, C#, C++, XML, SQL, Windows Forms, HTML, CSS, etc., etc., etc.

Comments and Discussions

 
GeneralMy vote of 3 PinprofessionalJohn Saunders, Microsoft MVP27-Feb-14 4:40 
GeneralRe: My vote of 3 PinmemberSteve Wellens28-Feb-14 16:03 
GeneralRe: My vote of 3 PinprofessionalJohn Saunders, Microsoft MVP28-Feb-14 16:30 
GeneralRe: My vote of 3 PinmemberSteve Wellens28-Feb-14 17:05 
GeneralRe: My vote of 3 PinprofessionalJohn Saunders, Microsoft MVP28-Feb-14 20:21 
GeneralRe: My vote of 3 PinmemberSteve Wellens1-Mar-14 3:33 
GeneralMy vote of 5 PinmemberJack_32127-May-12 3:39 
QuestionMy vote is above 5 PinmemberAlireza_136224-Apr-12 21:39 
QuestionWindowsForms issue solved PinmemberMartin Garcia2-Jan-12 0:43 
AnswerRe: WindowsForms issue solved PinmemberSteve Wellens2-Jan-12 2:41 
GeneralRe: WindowsForms issue solved PinmemberMartin Garcia2-Jan-12 2:50 
GeneralRe: WindowsForms issue solved PinmemberSteve Wellens2-Jan-12 6:06 
GeneralSessions In WCF? PinmemberEastManJack9-May-11 4:54 
GeneralNullable and coalescing Pinmemberdybkjaer11-Nov-10 1:59 
GeneralRe: Nullable and coalescing PinmemberSteve Wellens11-Nov-10 3:05 
GeneralMy vote of 5 PinmemberN-DK12-Sep-10 22:44 
GeneralNice read PinmemberArne0018-Jul-10 20:38 
GeneralMy vote of 5 Pinmemberkeyur s28-Jun-10 3:01 
GeneralSimple, Helpfull, Funny! PinmemberDaniella11-Jan-10 23:15 
GeneralGood article PinmemberDonsw16-May-09 16:49 
GeneralNice (but newbie's use with caution) PinmemberJeffCirceo13-May-09 5:10 
GeneralUpdate PinmemberSteve Wellens2-May-09 16:33 
GeneralRe: Update PinmemberEastManJack9-May-11 3:43 
GeneralRe: Update PinmemberSteve Wellens12-May-11 7:08 
GeneralRe: Update PinprofessionalJohn Saunders, Microsoft MVP27-Feb-14 4:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 11 May 2009
Article Copyright 2009 by Steve Wellens
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid