views:

251

answers:

1

Without getting into the 'Stateful services are bad' discussion... How do you create one?

From the lack of helpful search results.. it seems either I'm searching for the wrong terms or it is being actively discouraged. The best link i could find was this one on MSDN

To give a brief context of what my current app looks like. Rails Web App => ASP.Net Xml webservice => Legacy C#/C++ code

So far so good. Now it turns out that when I make the first request to a WebMethod, it needs to launch some processes/resources that are expensive to create-use-dispose on each call. So I was looking at reusing these resources.

First I tried making them into member variables - only to have the light-bulb moment that each request is serviced by a new instance of MyWebService class and on a different thread at that.

The link suggests that the way to do this is

  • to use the Session hash / properties collection in case the state is per-user.
  • to use the Application hash / properties collection in case the state is global

Questions:

  1. Is this right? Am I missing some magic attributes ?
  2. I tried the Application hashtable method... populating certain known keys on the first request. However on the second request, the hashtable is in a clean/no items state.
  3. How do I handle Synchronization ? the .net way of locking on a private member object won't work.

My Web Service class looks like this..

[WebService(Namespace = "http://Walkthrough/XmlWebServices/", 
      Description="A temperature conversion xml web service")]
   [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
   [System.ComponentModel.ToolboxItem(false)]

   public class TemperatureConverter : System.Web.Services.WebService, IDisposable
   {
      [WebMethod(Description = "This method converts celsius to fahrenheit")]
      public double convert_fahrenheit_to_celsius(double temp_in_fahrenheit)
      {
         /// code
      }
    }

Update: I'm still struggling with Q#2. There's some strange behavior

protected void Application_Start(object sender, EventArgs e)  // global.asax.cs
{
         Application["UserName"] = "Gishu";
}

myWebMethod // MyWebService.cs
{
  if (Application["myKey"] == null)
    LoadHeavyObjectsAndCacheKeys(); // set Application["myKey"] between  Application.Lock() Unlock() calls.
  ...
}

The "UserName" key write succeeds - it is present in the hash. However the key-value pairs that I write within my web method don't survive the current web request. On the next request, the hashtable still has only one item - "UserName". Since this is ApplicationState, I assume I dont have to set the EnableSession property to true.

+1  A: 

Yes, you should use Session state for per-session data, and Application state for application-wide data.

Your web service operations need to have the [WebMethod(EnableSession=true)] attribute on them.

John Saunders
Thanks for the confirmation.. however I'm having some trouble getting the Application state to persist.. See update to my question. Also I'm running the ASP.Net development server - can that cause this behavior ?
Gishu
Suggest you simplify as a debug strategy. Copy the code from Application_Start into the web method, but then change the key to "Username1". See if _this_ cell is initialized the second time you call the web method.
John Saunders