.netwcfstatelessbasichttpbindinginstancecontextmode

is InstanceContextMode.Single available for WCF basicHttpBinding?


As I understand from this article:

Single: This will help us to share the data globally. We can create only one instance and the same instance will be reused on the subsequent calls. Same like Per Session this will work with all bindings except basicHttpBinding.

InstanceContextMode.Single not available for basicHttpBinding.

But according to this answer it works.

This article adds confusion.

I'd like to get clear answer and explanation.


Solution

  • InstanceContextMode.Single will force the WCF engine to create a single instance of your service class through the lifetime of your service. This means that all requests will share the same instance rather than creating one per request.

    This is entirely possible with basicHttpBinding.

    Here is an example using basicHttpBinding and InstanceContextMode.Single:

    First my Service class which has private field that keeps the count of requests:

    using System.ServiceModel;
    
    namespace WcfService1
    {
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
        public class Service1 : IService1
        {
            private int _singleCounter = 0;//this will be preserved across requests
            public Service1() 
            {
                //this constructor executes only ONCE
            }
            public string GetData()
            {
                //this will increment with each request 
                //because it is a SINGLE instance the count
                //will be preserved
                _singleCounter++;
                return string.Format("Requests on this instance: {0}", _singleCounter);
            }
        }
    }
    

    Now my Service Contract:

    using System.ServiceModel;
    
    namespace WcfService1
    {    
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            string GetData();
        }
    }
    

    Lastly here is my config file with a single binding using basicHttpBinding:

    <?xml version="1.0"?>
    <configuration>
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5"/>
      </system.web>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>    
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
        <directoryBrowse enabled="true"/>
      </system.webServer>
    </configuration>
    

    Now using the default WCF Test Client that comes with Visual Studio here are the results:

    First call the count is 1: enter image description here

    Second call the count is 2: enter image description here

    A few clicks later the count is still being preserved: enter image description here

    I am not sure why some articles state that InstanceContextMode.Single is not supported by basicHttpBinding. It is obviously not true.

    I use InstanceContextMode.Single combined with ConcurrencyMode.Multiple for high throughput services all the time.

    It also has the advantage that you can keep some "state" during the lifetime of the service that can be shared across all requests. For example I keep commonly used data in private fields to avoid loading it from the database on every request etc.