O WCF provê três modelos diferente de controle de instâncias, sendo estes modelos:
Per call instance mode – Uma nova instância do serviço WCF é criada para cada chamada de método invocada por um cliente e destruida após a resposta ser enviada.
Per session instance mode – Apenas uma instância de um serviço é criada para um conjunto de integrações com o cliente. A instância do serviço só é destruída quando o cliente termina suas requisições.
Single instance mode – Uma instância global do serviço é criada, e desta forma fica responsável por receber e processar todas as requisições de todos os clientes.
A enumeração InstanceContextMode é utilizada para indicar qual modelo de instâncias será utilizado pelo serviço durante o seu funcionamento. Ela determina qual associação deve existir entre o canal e o serviço.
Mas, para manter a instância de um serviço ativa, apenas alterar o modo de controle de instâncias não é suficiente. Para associar um cliente com uma instância particular do WCF, é preciso que o WCF consiga identificar o cliente que fez o invoque do método. Um modo de fazer isso é utilizar uma transport-level session, isto é, uma conexão contínua, tais como as mantidas pelos protocolos TCP e IPC.
Desta maneira, para mantermos uma sessão ativa entre o cliente e o serviço WCF, é preciso usar um binding como NetTcpBinding ou NetNamedPipeBinding. O WsHttpBinding também pode ser utilizado, pois ele é capaz de emular uma transport-level session, pois utiliza um ID de sessão no cabeçalho das mensagens, para identificar exclusivamente cada cliente. Em contrapartida, o BasicHttpBinding não pode ser utilizado, pois ele recria uma conexão sempre, o que impede a identificação do cliente pelo serviço WCF.
Neste post demonstro um exemplo de como manter a instância de um serviço durante múltiplas chamadas de método para um cliente. Neste exemplo configurei o serviço para utilizar WsHttpBinding. Os blocos necessários para implementação do serviço estão distribuídos a seguir.
Configuração do WsHttpBinding
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="NewBehavior"> <serviceDebug /> <serviceMetadata httpGetEnabled="true"/> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="NewBehavior" name="WcfHostService.StatusService"> <endpoint address="" binding="wsHttpBinding" contract="WcfHostService.IStatusService"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="" contract="IMetadataExchange" /> </service> </services> </system.serviceModel>
Código do Serviço
[DataContract] public enum Status { [EnumMember] Stopped = 1, [EnumMember] Initializing = 2, [EnumMember] Processing = 3, [EnumMember] Ready = 4 } [ServiceContract] public interface IStatusService { [OperationContract] void ChangeStatus(Status newStatus); [OperationContract] Status GetCurrentStatus(); [OperationContract] int GetNumberOfInteractions(); } [ServiceKnownType(typeof(Status))] [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class StatusService : IStatusService { private Status _currentStatus; private int _interactions; public StatusService() { this._currentStatus = Status.Stopped; this._interactions = 0; } public void ChangeStatus(Status newStatus) { this._interactions++; this._currentStatus = newStatus; } public int GetNumberOfInteractions() { return this._interactions; } public Status GetCurrentStatus() { return this._currentStatus; } }
Código da Camada Cliente
static void Main(string[] args) { int interactions = 0; var client = new StatusService.StatusServiceClient(); // Change status to Initializing client.ChangeStatus(StatusService.Status.Initializing); interactions = client.GetNumberOfInteractions(); Console.WriteLine("Current status is: " + client.GetCurrentStatus()); Console.WriteLine("Interaction number: " + interactions); // Change status to Processing client.ChangeStatus(StatusService.Status.Processing); interactions = client.GetNumberOfInteractions(); Console.WriteLine("Current status is: " + client.GetCurrentStatus()); Console.WriteLine("Interaction number: " + interactions); // Change status to Ready client.ChangeStatus(StatusService.Status.Ready); interactions = client.GetNumberOfInteractions(); Console.WriteLine("Current status is: " + client.GetCurrentStatus()); Console.WriteLine("Interaction number: " + interactions); }
Por
MSc. Fernando Henrique Inocêncio Borba Ferreira.
Microsoft Most Valuable Professional – Visual C#
Referências:
http://www.codeproject.com/Articles/86007/3-ways-to-do-WCF-instance-management-Per-call-Per
http://msdn.microsoft.com/pt-br/library/system.servicemodel.instancecontextmode.aspx
http://msdn.microsoft.com/pt-br/library/ms752230.aspx
http://msdn.microsoft.com/en-us/library/ff650619.aspx