Example 4-1. The ServiceBehaviorAttribute used to configure instance context mode
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WCFServiceProgramming { public enum InstanceContextMode { PerCall, PerSession, Single } [AttributeUsage(AttributeTargets.Class)] public sealed class ServiceBehaviorAttribute : Attribute { public InstanceContextMode InstanceContextMode { get; set; } // ... } }
Example 4-2. Per-call service and client(Server)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; using System.Diagnostics; namespace WCFServiceProgramming { [ServiceContract] public interface IMyContract { [OperationContract] void MyMethod(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] class MyService : IMyContract, IDisposable { int m_Counter = 0; MyService() { Trace.WriteLine("MyService.MyService()"); } public void MyMethod() { m_Counter++; Trace.WriteLine("Counter = " + m_Counter); } public void Dispose() { Trace.WriteLine("MyService.Dispose()"); } } }
Example 4-2. Per-call service and client(Client)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Channels; using System.ServiceModel; using System.Runtime.Serialization; namespace WCFServiceProgramming { class MyContractClient : ClientBase<IMyContract>, IMyContract { public void MyMethod() { Channel.MyMethod(); } } class Program { static void Main(string[] args) { MyContractClient proxy = new MyContractClient(); proxy.MyMethod(); proxy.MyMethod(); proxy.Close(); } } }
//Possible Output
MyService.MyService( )
Counter = 1
MyService.Dispose( )
MyService.MyService( )
Counter = 1
MyService.Dispose( )
Example 4-3. Implementing a per-call service
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; using System.Diagnostics; using System.Runtime.Serialization; namespace WCFServiceProgramming { [DataContract] class Param { } [ServiceContract] interface IMyContract { [OperationContract] void MyMethod(Param stateIdentifier); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] class MyService : IMyContract, IDisposable { public void MyMethod(Param stateIdentifier) { GetState(stateIdentifier); DoWork(); SaveState(stateIdentifier); } private void GetState(Param stateIdentifier) { } private void DoWork() { } private void SaveState(Param stateIdentifier) { } public void Dispose() { } } }
Example 4-4. Per-session service and client(Service)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; using System.Diagnostics; using System.Runtime.Serialization; namespace WCFServiceProgramming { [ServiceContract(SessionMode = SessionMode.Required)] interface IMyContract { [OperationContract] void MyMethod(); } class MyService : IMyContract, IDisposable { int m_Counter = 0; MyService() { Trace.WriteLine("MyService.MyService()"); } public void MyMethod() { m_Counter++; Trace.WriteLine("Counter = " + m_Counter); } public void Dispose() { Trace.WriteLine("MyService.Dispose()"); } } }
Example 4-4. Per-session service and client(Client)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Channels; using System.ServiceModel; using System.Runtime.Serialization; namespace WCFServiceProgramming { class MyContractClient : ClientBase<IMyContract>, IMyContract { public void MyMethod() { Channel.MyMethod(); } } class Program { static void Main(string[] args) { MyContractClient proxy = new MyContractClient(); proxy.MyMethod(); proxy.MyMethod(); proxy.Close(); } } }
//Output
MyService.MyService( )
Counter = 1
Counter = 2
MyService.Dispose( )
Example 4-5. Enabling reliability for per-session services(Host Configuration)
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="false" targetFramework="4.0" /> </system.web> <!-- Host Configuration --> <system.serviceModel> <services> <service name="MyPerSessionService"> <endpoint address="net.tcp://localhost:8000/MyPerSessionService" binding="netTcpBinding" bindingConfiguration="TCPSession" contract="IMyContract" /> </service> </services> <bindings> <netTcpBinding> <binding name="TCPSession"> <reliableSession enabled="true"/> </binding> </netTcpBinding> </bindings> </system.serviceModel> </configuration>
Example 4-5. Enabling reliability for per-session services(Client Configuration)
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="false" targetFramework="4.0" /> </system.web> <!-- Client Configuration --> <system.serviceModel> <client> <endpoint address="net.tcp://localhost:8000/MyPerSessionService" binding="netTcpBinding" bindingConfiguration="TCPSession" contract="IMyContract"/> </client> <bindings> <netTcpBinding> <binding name="TCPSession"> <reliableSession enabled="true"/> </binding> </netTcpBinding> </bindings> </system.serviceModel> </configuration>
Example 4-6. A singleton service and client(Service)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; using System.Diagnostics; using System.Runtime.Serialization; namespace WCFServiceProgramming { ///////////////////////// Service code ///////////////////// [ServiceContract(SessionMode = SessionMode.Required)] interface IMyContract { [OperationContract] void MyMethod(); } [ServiceContract(SessionMode = SessionMode.NotAllowed)] interface IMyOtherContract { [OperationContract] void MyOtherMethod(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] class MySingleton : IMyContract, IMyOtherContract, IDisposable { int m_Counter = 0; public MySingleton() { Trace.WriteLine("MySingleton.MySingleton( )"); } public void MyMethod() { m_Counter++; Trace.WriteLine("Counter = " + m_Counter); } public void MyOtherMethod() { m_Counter++; Trace.WriteLine("Counter = " + m_Counter); } public void Dispose() { Trace.WriteLine("Singleton.Dispose( )"); } } }
Example 4-6. A singleton service and client(Client)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Channels; using System.ServiceModel; using System.Runtime.Serialization; namespace WCFServiceProgramming { ///////////////////////// Client code ///////////////////// class MyContractClient : ClientBase<IMyContract>, IMyContract { public void MyMethod() { Channel.MyMethod(); } } class MyOtherContractClient : ClientBase<IMyOtherContract>, IMyOtherContract { public void MyOtherMethod() { Channel.MyOtherMethod(); } } class Program { static void Main(string[] args) { MyContractClient proxy1 = new MyContractClient(); proxy1.MyMethod(); proxy1.Close(); MyOtherContractClient proxy2 = new MyOtherContractClient(); proxy2.MyOtherMethod(); proxy2.Close(); } } }
//Output
MySingleton.MySingleton( )
Counter = 1
Counter = 2
Example 4-7. Initializing and hosting a singleton (Service)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; using System.Diagnostics; using System.Runtime.Serialization; namespace WCFServiceProgramming.Library { ///////////////////////// Service code ///////////////////// [ServiceContract(SessionMode = SessionMode.Required)] public interface IMyContract { [OperationContract] void MyMethod(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class MySingleton : IMyContract, IDisposable { int m_Counter = 0; public int Counter { get { return m_Counter; } set { m_Counter = value; } } public void MyMethod() { m_Counter++; Trace.WriteLine("Counter = " + m_Counter); } } }
Example 4-7. Initializing and hosting a singleton (Host)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using WCFServiceProgramming.Library; using System.ServiceModel; namespace WCFServiceProgramming.Host { class Program { static void Main(string[] args) { MySingleton singleton = new MySingleton(); singleton.Counter = 42; ServiceHost host = new ServiceHost(singleton); host.Open(); // Do some blocking calls then host.Close(); } } }
Example 4-7. Initializing and hosting a singleton (Client)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Channels; using System.ServiceModel; using System.Runtime.Serialization; using WCFServiceProgramming.Library; namespace WCFServiceProgramming.Client { ///////////////////////// Client code ///////////////////// class MyContractClient : ClientBase<IMyContract>, IMyContract { public void MyMethod() { Channel.MyMethod(); } } class Program { static void Main(string[] args) { MyContractClient proxy = new MyContractClient(); proxy.MyMethod(); proxy.Close(); } } }
Example 4-8. Using ReleaseServiceInstance( )
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; using System.Diagnostics; using System.Runtime.Serialization; namespace WCFServiceProgramming.Library { [ServiceContract(SessionMode = SessionMode.Required)] public interface IMyContract { [OperationContract] void MyMethod(); } public class MyService : IMyContract, IDisposable { public void MyMethod() { //Do some work then OperationContext.Current.InstanceContext.ReleaseServiceInstance(); } public void Dispose() { } } }
Example 4-9. Administrative throttling
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="MyService" behaviorConfiguration="ThrottleBehavior"> </service> </services> <behaviors> <serviceBehaviors> <behavior name="ThrottleBehavior"> <serviceThrottling maxConcurrentCalls="12" maxConcurrentSessions="34" maxConcurrentInstances="56"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
Example 4-10. Programmatic throttling
using System; using System.Collections.Generic; using System.Linq; using System.Text; using WCFServiceProgramming.Library; using System.ServiceModel; using System.ServiceModel.Description; namespace WCFServiceProgramming.Host { class Program { static void Main(string[] args) { ServiceHost host = new ServiceHost(typeof(MyService)); ServiceThrottlingBehavior throttle; throttle = host.Description.Behaviors.Find<ServiceThrottlingBehavior>(); if (throttle == null) { throttle = new ServiceThrottlingBehavior(); throttle.MaxConcurrentCalls = 12; throttle.MaxConcurrentSessions = 34; throttle.MaxConcurrentInstances = 56; host.Description.Behaviors.Add(throttle); } host.Open(); // Do some blocking calls then host.Close(); } } }
Example 4-11. Extending ServiceHost<T> to handle throttling
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Description; using System.Diagnostics; using System.ServiceModel.Channels; namespace WCFServiceProgramming.Host { public class ServiceHost<T> : ServiceHost { public void SetThrottle(int maxCalls, int maxSessions, int maxInstances) { ServiceThrottlingBehavior throttle = new ServiceThrottlingBehavior(); throttle.MaxConcurrentCalls = maxCalls; throttle.MaxConcurrentSessions = maxSessions; throttle.MaxConcurrentInstances = maxInstances; SetThrottle(throttle); } private void SetThrottle(ServiceThrottlingBehavior throttle) { SetThrottle(throttle, false); } private void SetThrottle(ServiceThrottlingBehavior serviceThrottle, bool overrideConfig) { if (State == CommunicationState.Opened) { throw new InvalidOperationException("Host is already opened"); } ServiceThrottlingBehavior throttle = Description.Behaviors.Find<ServiceThrottlingBehavior>(); if (throttle != null && overrideConfig == false) { return; } if (throttle != null) //overrideConfig == true, remove the configured one { Description.Behaviors.Remove(throttle); } if (throttle == null) { Description.Behaviors.Add(serviceThrottle); } } public ServiceThrottlingBehavior ThrottleBehavior { get { return Description.Behaviors.Find<ServiceThrottlingBehavior>(); } } } }