Geeks With Blogs

News




What I do:

Identity Mine

MVVM Light

GalaSoft


What I am:

Microsoft Most Valuable Professional, Client Application Development

Microsoft Certified Technology Specialist, Windows Presentation Foundation

WPF disciples


Social:


View my profile on LinkedIn

XING
Creative Commons License
Diary of a Code Trotter by Laurent Bugnion is licensed under a Creative Commons Attribution 3.0 Unported License

All source code on this blog is licensed under the MIT license.

Copyright (c) 2006 - 2011 GalaSoft Laurent Bugnion

Laurent Bugnion (GalaSoft) Diary of a Code Trotter
UPDATE: not a bug
You got to love the internet. Minutes after I wrote about what I thought was a bug in WPF, Joseph Cooney pointed me to this page which explains how to save the cookie on the client to avoid losing the SessionID. Seems that I have been spoilt by my years of ASP.NET programming, where the browser stores the cookies automatically. I will update the example, and will post again about this soon!
Problem
This prototype demonstrates that, in WPF, the SessionID used when calling web services is not saved by default.
Using SessionID in web services
When a client calls a web service the first time, it is assigned a unique identifier called SessionID, which is saved using cookies. When the following calls arrive, the SessionID is read from the cookies collection, and the Session object (HttpSessionState) is retrieved. This object can be used to store state information related with the calling client.
In order to make the Session object accessible to web methods, the "WebMethod" attribute decorating the web method uses the EnableSession attribute, which must be set to true.
[WebService( Namespace = "http://www.galasoft-lb.ch/" )]
[WebServiceBinding( ConformsTo = WsiProfiles.BasicProfile1_1 )]
[ToolboxItem( false )]
public class Service1 : System.Web.Services.WebService
{
  [WebMethod( EnableSession=true )]
  public string GetSessionId()
  {
    return Session.SessionID;
  }
}
Web method accessing the Session
Using web services in WPF
Windows Presentation Foundation (WPF) can consume ASMX web services easily, because they relay on the .NET framework. In .NET 2.0, using a web service is as easy as adding a Web Reference to the project (Right-click on the project / Add Web Reference...). Enter the URL of the ASMX file, and select the service you want to use.
Once this is done, the web service is available as a proxy, meaning that calling a method on the proxy object will automatically send the web service request, wait for the answer and parse the response, providing the client with the corresponding result.
Web methods can be called synchronously and asynchronously, but the async mode is better, because it doesn't block the client while the request is sent and processed. The client simply registers a method to the "Completed" event of the corresponding method. In Visual Studio 2005, this is very easy to do: Select the "Completed" event you want to register with, then type "+=". This presents you with a dialog asking if you want Studio to insert the corresponding code. Press "Tab" to confirm, and then "Tab" again to declare the method.
private void bnGetSessionId_Click( object sender, RoutedEventArgs e )
{
  try
  {
    GetSessionIdService.Service1 oSessionIdService
      = new GetSessionIdService.Service1();
    oSessionIdService.GetSessionIdCompleted
      += new GetSessionIdService.GetSessionIdCompletedEventHandler(
        oSessionIdService_GetSessionIdCompleted );
        oSessionIdService.GetSessionIdAsync();
  }
  catch ( Exception ex )
  {
    lblSessionId.Text = ex.Message;
    lblSessionId.Foreground = Brushes.Red;
  }
}
Calling the wen method asynchronously
The only step remaining now it to handle the response, in the corresponding event handler.
private void oSessionIdService_GetSessionIdCompleted( object sender,
  GetSessionIdService.GetSessionIdCompletedEventArgs e )
{
  if ( e != null
    && e.Result != null
    && e.Result.Length > 0 )
  {
    if ( lblSessionId.Text.Length > 0 )
    {
      lblSessionId.Text += Environment.NewLine;
    }
    lblSessionId.Text += "SessionID at "
      + DateTime.Now.ToLongTimeString()
      + ": " + e.Result;
    lblSessionId.Foreground = Brushes.Black;
  }
  else
  {
    lblSessionId.Text = "Unknown error";
    lblSessionId.Foreground = Brushes.Red;
  }
}
Processing the Response
Consequences
Many web services use the Session object to store state information. Most web application nowadays are stateful to enable a better user experience. It is therefore necessary to save the SessionID on the WPF client when using web services, or else on every request, a new Session object is created. My prototype demonstrates the fact: Every time you call the service, it returns a different session ID.
In order to save the SessionID in a cookie on the client, a CookieContainer must be used. This page at MSDN shows how.
Different session ID on every call
Different session ID on every call
Posted on Wednesday, October 4, 2006 10:18 AM Technical stuff , .NET , WPF | Back to top


Comments on this post: WPF: Inconsistent SessionID when using web services

# re: WPF bug (?): Inconsistent SessionID when using web services
Requesting Gravatar...
I was not able to download the code (I got a 404) but I think you need to assign a cookie container to the client proxy if you want to retain the session cookie between requests. This is described (poorly) here http://msdn2.microsoft.com/en-us/library/system.web.services.protocols.httpwebclientprotocol.cookiecontainer.aspx
Left by Joseph Cooney on Oct 04, 2006 1:45 PM

# re: WPF bug (?): Inconsistent SessionID when using web services
Requesting Gravatar...
Sorry for the 404, this is corrected now.

I will check the link you gave me and try again. Thanks!
Left by Laurent on Oct 04, 2006 2:03 PM

# re: WPF: Inconsistent SessionID when using web services
Requesting Gravatar...
Maybe I'm missing something, but I don't see what this has to do with WPF?

The issue you describe here is entirely to do with web service proxies that are generated for you when you use the Add Web Reference feature of Visual Studio. That's not a WPF feature - it works the same way whether you use it from WPF, Windows Forms, an ASP.NET app, a console app, or anything else.

So you'd have to use a cookie container to ensure that cookies are remembered if you were using any of these other technologies as the client. (Even ASP.NET - it may be a web technology, so you might think it's cookie aware, but actually, as far as I know when it's acting as a web service *client* it doesn't remember cookies unless you provide a container.)

I don't see anything in this web page that is specific to WPF. (Other than the fact that you happened to be writing a WPF app when you ran into this non-WPF-specific issue.) Have I missed something?
Left by Ian Griffiths on Nov 07, 2006 2:38 PM

# re: WPF: Inconsistent SessionID when using web services
Requesting Gravatar...
Ian,

You are totally right. When I wrote this, I thought that this was a WPF issue, because in our study of the technology, we encountered many places where the technology was unfinished, and some features were unavailable. Hence the confusion.

Since then I wrote a follow up available here
http://geekswithblogs.net/lbugnion/archive/2006/10/11/93743.aspx

You are exactly right that the technology used here is not WPF-only, but also applies to Windows Forms.

Greetings
Laurent
Left by Laurent on Nov 07, 2006 3:00 PM

Comments have been closed on this topic.
Copyright © Laurent Bugnion | Powered by: GeeksWithBlogs.net