paparazzo
paparazzo

Reputation: 45096

WCF Manage Session State Information

What is the most scaleble way to manage state in a WCF.

I just need a single variable to indicate a session and I will manage information relative to the session in a MSSQL. I don't need to know when a session ends. Once a day I will just clear out any old sessions.

It appears SessionID is that variable.

For scale I am using Per Call as the ctor is empty. I don't think I need per session.

In my simple EightBall test I am getting a SessionID that represents a session. But I am just testing on a single box.

What worries me is that I see some documentation that I need to set ReliableSessionBindingElement On and it is Off by default.

Is SessionID going to be a reliable indicator of session in the following configuration?

<system.serviceModel>
    <services>
      <service name="MajicEightBallServiceLib.MagicEightBallService"
               behaviorConfiguration="EightBallServiceMEXBehavior" >
        <endpoint address=""
                  binding="wsHttpBinding"
                  contract="MajicEightBallServiceLib.IEightBall" />
        <endpoint address="mex"
                  binding ="mexHttpBinding"
                  contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/MagicEightBallService"/>
          </baseAddresses>
        </host>             
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="EightBallServiceMEXBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

[ServiceBehavior (InstanceContextMode=InstanceContextMode.PerCall)]
public class MagicEightBallService : IEightBall
{
    public MagicEightBallService()
    {
        Console.WriteLine("Eightball awaits your question ...");
    }
    public string ObtainAnswerToQuestion(string userQuestion)
    {
        return "maybe " + OperationContext.Current.SessionId.ToString();
    }

    public sDoc GetSdoc(int sID)
    {
        List<sDocProp> props = new List<sDocProp>();
        sDocProp prop1 = new sDocProp { ID = 1, Name = "Prop1", ArrivalStatus = ArrivalStatus.OnTime };
        props.Add(prop1);
        sDocPropStringSV prop2 = new sDocPropStringSV { ID = 1, Name = "Prop1", ArrivalStatus = ArrivalStatus.OnTime, Value = "StrValue1" };
        props.Add(prop2);
        sDoc sDoc = new sDoc { sID = sID, sParID = 1, Props = props, SessionID = OperationContext.Current.SessionId.ToString() };
        return sDoc;
    }

Upvotes: 1

Views: 1745

Answers (1)

Dmitry Harnitski
Dmitry Harnitski

Reputation: 6008

WCF supports 4 types of sessions and reliable session is only one of them. So you do not necessary need to turn set ReliableSessionBindingElement On to enable session. You can use other session types.

The System.ServiceModel.Channels.ReliableSessionBindingElement, which implements the WS-ReliableMessaging specification, provides support for reliable sessions in which messages are delivered in order and exactly once, enabling confidence even when messages travel across multiple nodes during the conversation.

Actually wsHttpBinding by default uses a secure session which encrypts and digitally signs messages.

Is SessionID going to be a reliable indicator of session in the following configuration?

Service can check if your binding configured to use session using ServiceContractAttribute.SessionMode attribute.

The following service contract requires that configured bindings use sessions.

[ServiceContract(SessionMode = SessionMode.Required)]
public interface IEightBall

http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.sessionmode.aspx

What is the most scaleble way to manage state in a WCF.

InstanceContextMode.PerCall is the right choice if your code does not depend on any session data except Session ID. Session ID is part of WCF message so there is no need to keep InstanceContext longer than it is necessary to process request.

Another question:

Is SessionID going to be a reliable indicator of session in the following configuration?

Answer is YES. Below is reverse-engineered code of property System.ServiceModel.OperationContext.SessionId. As you can see SessionId is loaded from Channel.Session and not empty SessionId value is returned only if Session is not null.

public string SessionId
{
    get
    {
        if (this.channel != null)
        {
            IChannel innerChannel = this.channel.InnerChannel;
            if (innerChannel != null)
            {
                ISessionChannel<IDuplexSession> sessionChannel = innerChannel as ISessionChannel<IDuplexSession>;
                if (sessionChannel != null && sessionChannel.Session != null)
                {
                    return sessionChannel.Session.Id;
                }
                ISessionChannel<IInputSession> sessionChannel2 = innerChannel as ISessionChannel<IInputSession>;
                if (sessionChannel2 != null && sessionChannel2.Session != null)
                {
                    return sessionChannel2.Session.Id;
                }
                ISessionChannel<IOutputSession> sessionChannel3 = innerChannel as ISessionChannel<IOutputSession>;
                if (sessionChannel3 != null && sessionChannel3.Session != null)
                {
                    return sessionChannel3.Session.Id;
                }
            }
        }
        return null;
    }
}

Upvotes: 2

Related Questions