In PerSession how do I get Dispose() on the service to fire? In the code below Dispose() does not get called. Neither when I call .Close() nor if I let the session time out.
If I change the service to PerCall Dispose() is called (with each method call). With PerSession I am getting a session (tested with serviceStartTime).
Service
[ServiceBehavior (InstanceContextMode=InstanceContextMode.PerSession)]
public class MagicEightBallService : IEightBall, IDisposable
{
private DateTime serviceStartTime;
public void Dispose()
{
Console.WriteLine("Eightball dispose ... " + OperationContext.Current.SessionId.ToString());
}
public MagicEightBallService()
{
serviceStartTime = DateTime.Now;
Console.WriteLine("Eightball awaits your question " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString());
}
public string ObtainAnswerToQuestion(string userQuestion)
{
return "maybe " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString();
}
Client
using (EightBallClient ball = new EightBallClient())
{
while (true)
{
Console.Write("Your question: ");
string question = Console.ReadLine();
if (string.IsNullOrEmpty(question)) break;
try
{
string answer = ball.ObtainAnswerToQuestion(question);
Console.WriteLine("8-ball says: {0}", answer);
}
catch (Exception Ex)
{
Console.WriteLine("ball.ObtainAnswerToQuestion exception " + Ex.Message);
}
}
ball.Close();
}
Service-Contract
[ServiceContract (SessionMode = SessionMode.Required)]
public interface IEightBall
{
[OperationContract]
string ObtainAnswerToQuestion(string userQuestion);
[OperationContract]
sDoc GetSdoc(int sID);
DateTime CurDateTime();
}
Host
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ISampleService"
closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:10:00">
<security mode="Message" />
<reliableSession ordered="true"
inactivityTimeout="00:10:00"
enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="MajicEightBallServiceLib.MagicEightBallService"
behaviorConfiguration="EightBallServiceMEXBehavior" >
<endpoint address=""
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISampleService"
contract="MajicEightBallServiceLib.IEightBall">
</endpoint>
<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>
</configuration>
namespace MagicEightBallServiceHost
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("**** Console Based WCF Host *****");
using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService)))
{
serviceHost.Open();
Console.WriteLine("The service is running");
Console.ReadLine();
}
}
}
}
Dispose()
method will be fired. The only question question is "When?".
Answer to that question depends on the service configuration.
There are several possible scenarios:
Dispose()
is fired when session is closed for PerSession
context mode. So we need to check how long does session live in different scenarios.
For some configurations (for example default BasicHttpBinding
) session is not started at all. In case of session-less configuration PerCall
and PerSession
context modes have no difference and Dispose
method will be called very soon after your main method executed.
When Session
is Enabled it can be closed explicitly by client or by timeout. Normally it is controlled by client. Client initiates session before making first call to service and closes it when Client object is closed.
ServiceClient proxy = new ServiceClient();
Console.WriteLine(proxy.GetData(123));
proxy.Close();
proxy.Close()
method above closes the session in server what in turn executes Dispose()
.
Session management is a big performance driver because it requires additional calls between client and server to be performed.
So normally Dispose
will be called when Client wants to close the session.
If client did not close session for any reason it will be closed by service host after certain period of time. That period is controlled by Binding.ReceiveTimeout property. Default value for that property is 10 min.
Session will be closed and (Dispose()
fired) if nobody sent request to server with certain Session Id for 10 min.
This default timeout can be changed by setting receiveTimeout
to some shorter value in web.config.
<wsHttpBinding>
<binding name="wsHttpEndpointBinding" receiveTimeout="00:00:05">
</binding>
</wsHttpBinding>
ReliableSession.InactivityTimeout is additionally checked when Reliable session is enabled. It is also defaulted to 10 min.
It works as expected in self-hosted and IIS-hosted services.
Try to update your client code as follows to test:
using (EightBallClient ball = new EightBallClient())
{
ball.ObtainAnswerToQuestion("test");
ball.Close();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With