views:

41

answers:

3

I have a WCF application , with multiple WSDL webservices, hosted in IIS7 on Windows Server 2008 64Bit.

The application requires a singleton to be assigned with some configuration values once, when the first webservice method is invoked (no matter what is invoked first).

Edit: The backend of the system requires the use of this singleton approach.

I get the configuration assigned once, but the values become null again....

Here is the code (simplified):

public class SingletonSettings 
{
    private static readonly SingletonSettings _s;

    public SingletonSettings Instance { get {return _s;} }

    public object SomeValue { get; set; }
}

public abstract class AbstractWebservice 
{
    static AbstractWebservice() 
    {
        WebserviceGlobalInitializer.Initialize();
    }

}
//Just a webservice
public class Webservice1 : AbstractWebservice, ISomeServiceConctract1 
{
    public void DoStuff1();
}

//Just a webservice
public class Webservice2 : AbstractWebservice, ISomeServiceConctract2
{
    public void DoStuff2();
}

internal class WebserviceGlobalInitializer
    {
        private static readonly object Lock = new object();
        private static bool Initialized = false;

        public static void Initialize()
        {
            lock (Lock)
            {
                if (!Initialized)
                {
                    InitStuff();

                    Initialized = true;
                }
            }
        }

        private static void InitStuff()
        {            
            string s = SingletonSettings.Instance.SomeValue = "just a ref";
        }
    }

WebserviceGlobalInitializer.InitStuff() gets invoked only once. Still SingletonSettings.SomeValue becomes null.....

The issue occurs randomly.

I have tried

1) Invoking WebserviceGlobalInitializer.Initialize() from a normal constructor in the base class.

2) Commenting out: Initialized = true; in hope that the settings would then be initialized every time (causing massive overhead, so it would not be a long term solution anyway)

Still the value becomes null.

Any ideas?

A: 

You can use the WCF runtime infrastructure to take care of this for you. Try adding the following attribute to the WebService class:

[ServiceBehavior( ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]

Noel Abrahams
+1  A: 

With process recycling, all state that is not in session state or application state will disappear into the black hole. This, eye-openingly, includes the static variables, one of which is the singleton instance.

My gut feeling is that the InstanceContextMode of singleton has been implemented as a variable in the ASP.NET Application state. To check this, I will be doing some reflectoring today and will update my answer.

UPDATE

NO IT DOESN'T!!! With process recycling, even if you set the WCF Instancing mode to Single, you lose all state you had with your singleton instance (e.g. counter, whatever) with process recycling.

Aliostad
As long as i loose it all at once it is ok. I tested with manually pressing recycle and did not break. :-(
Fedearne
+1  A: 

After a few more days of searching i found the source of the problem. Aliostad's answer gave me a hint.

My webservice uses behavior configurations. One with authentication and one without. The authentication/session handling is implemented in an IDispatchMessageInspector which is invoked before the webservice is loaded.

The problem occurred when an application that uses my webservice was online when the application pool was recycled. Then application would then a request to a webservice using the authenticated behavior. The IDispatchMessageInspector implemention would then try to load the settings, but they have not yet been initialized from the static constructor in the webservice....

Thank you for the answers...

Fedearne