Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C++

Using Session State in a Web Service

Rate me:
Please Sign up or sign in to vote.
4.88/5 (36 votes)
11 May 2009CPOL3 min read 213.2K   77   36
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.

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:

C#
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:

C#
int Count;

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

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

C#
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…

C#
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:

C#
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.

C#
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.

This article was originally posted at http://weblogs.asp.net/stevewellens/privaterss.aspx

License

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


Written By
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

 
QuestionThanks Pin
Member 1360681014-Jan-18 22:40
Member 1360681014-Jan-18 22:40 
GeneralMy vote of 3 Pin
John Saunders, Former Microsoft MVP27-Feb-14 4:40
professionalJohn Saunders, Former Microsoft MVP27-Feb-14 4:40 
GeneralRe: My vote of 3 Pin
Steve Wellens28-Feb-14 16:03
Steve Wellens28-Feb-14 16:03 
GeneralRe: My vote of 3 Pin
John Saunders, Former Microsoft MVP28-Feb-14 16:30
professionalJohn Saunders, Former Microsoft MVP28-Feb-14 16:30 
GeneralRe: My vote of 3 Pin
Steve Wellens28-Feb-14 17:05
Steve Wellens28-Feb-14 17:05 
GeneralRe: My vote of 3 Pin
John Saunders, Former Microsoft MVP28-Feb-14 20:21
professionalJohn Saunders, Former Microsoft MVP28-Feb-14 20:21 
GeneralRe: My vote of 3 Pin
Steve Wellens1-Mar-14 3:33
Steve Wellens1-Mar-14 3:33 
GeneralMy vote of 5 Pin
Jack_32127-May-12 3:39
Jack_32127-May-12 3:39 
Thank you ...
QuestionMy vote is above 5 Pin
Alireza_136224-Apr-12 21:39
Alireza_136224-Apr-12 21:39 
QuestionWindowsForms issue solved Pin
Martin Garcia2-Jan-12 0:43
Martin Garcia2-Jan-12 0:43 
AnswerRe: WindowsForms issue solved Pin
Steve Wellens2-Jan-12 2:41
Steve Wellens2-Jan-12 2:41 
GeneralRe: WindowsForms issue solved Pin
Martin Garcia2-Jan-12 2:50
Martin Garcia2-Jan-12 2:50 
GeneralRe: WindowsForms issue solved Pin
Steve Wellens2-Jan-12 6:06
Steve Wellens2-Jan-12 6:06 
GeneralSessions In WCF? Pin
EastManJack9-May-11 4:54
EastManJack9-May-11 4:54 
GeneralNullable and coalescing Pin
dybkjaer11-Nov-10 1:59
dybkjaer11-Nov-10 1:59 
GeneralRe: Nullable and coalescing Pin
Steve Wellens11-Nov-10 3:05
Steve Wellens11-Nov-10 3:05 
GeneralMy vote of 5 Pin
N-DK12-Sep-10 22:44
professionalN-DK12-Sep-10 22:44 
GeneralNice read Pin
Arne0018-Jul-10 20:38
Arne0018-Jul-10 20:38 
GeneralMy vote of 5 Pin
keyur s28-Jun-10 3:01
keyur s28-Jun-10 3:01 
GeneralSimple, Helpfull, Funny! Pin
Daniella11-Jan-10 23:15
Daniella11-Jan-10 23:15 
GeneralGood article Pin
Donsw16-May-09 16:49
Donsw16-May-09 16:49 
GeneralNice (but newbie's use with caution) Pin
Jeff Circeo13-May-09 5:10
Jeff Circeo13-May-09 5:10 
GeneralUpdate Pin
Steve Wellens2-May-09 16:33
Steve Wellens2-May-09 16:33 
GeneralRe: Update Pin
EastManJack9-May-11 3:43
EastManJack9-May-11 3:43 
GeneralRe: Update Pin
Steve Wellens12-May-11 7:08
Steve Wellens12-May-11 7:08 

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

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