Utilizando sessões

Em aplicativos WCF (Windows Communication Foundation), uma sessão correlaciona um grupo de mensagens em uma conversa. As sessões do WCF são diferentes do objeto de sessão disponível em aplicativos ASP.NET, dão suporte a comportamentos diferentes e são controladas de maneiras diferentes. Este tópico descreve os recursos que as sessões habilitam em aplicativos WCF e como usá-los.

Sessões nos aplicativos do Windows Communication Foundation

Quando um contrato de serviço especifica que ele requer uma sessão, esse contrato está especificando que todas as chamadas (ou seja, as trocas de mensagens subjacentes que dão suporte às chamadas) devem fazer parte da mesma conversa. Se um contrato especificar que ele permite sessões, mas não requer uma, os clientes podem se conectar e estabelecer uma sessão ou não estabelecer uma sessão. Se a sessão terminar e uma mensagem for enviada pelo mesmo canal, uma exceção será gerada.

As sessões do WCF têm os seguintes principais recursos conceituais:

  • Eles são iniciados e encerrados explicitamente pelo aplicativo de chamada (o cliente WCF).

  • As mensagens entregues durante uma sessão são processadas na ordem em que são recebidas.

  • As sessões correlacionam um grupo de mensagens em uma conversa. Diferentes tipos de correlação são possíveis. Por exemplo, um canal baseado em sessão pode correlacionar mensagens com base em uma conexão de rede compartilhada, enquanto outro canal baseado em sessão pode correlacionar mensagens com base em uma marca compartilhada no corpo da mensagem. Os recursos que podem ser derivados da sessão dependem da natureza da correlação.

  • Não há nenhum armazenamento de dados geral associado a uma sessão WCF.

Se você estiver familiarizado com a classe System.Web.SessionState.HttpSessionState em aplicativos ASP.NET e a funcionalidade que ela fornece, você poderá observar as seguintes diferenças entre esse tipo de sessão e as sessões do WCF:

  • As sessões ASP.NET são sempre iniciadas pelo servidor.

  • As sessões ASP.NET são implicitamente desordenadas.

  • As sessões ASP.NET fornecem um mecanismo geral de armazenamento de dados entre solicitações.

Este tópico descreve:

  • O comportamento de execução padrão ao usar associações baseadas em sessão na camada do modelo de serviço.

  • Os tipos de recursos que as associações fornecidas pelo sistema baseadas em sessão do WCF fornecem.

  • Como criar um contrato que declare um requisito de sessão.

  • Como entender e controlar a criação e o encerramento da sessão e a relação da sessão com a instância de serviço.

Comportamento de execução padrão usando sessões

Uma associação que tenta iniciar uma sessão é chamada de associação baseada em sessão . Os contratos de serviço especificam que eles exigem, permitem ou recusam associações baseadas em sessão definindo a propriedade ServiceContractAttribute.SessionMode na interface do contrato de serviço (ou classe) como um dos valores de enumeração System.ServiceModel.SessionMode. Por padrão, o valor dessa propriedade é Allowed, o que significa que, se um cliente usa uma associação baseada em sessão com uma implementação de serviço WCF, o serviço estabelece e usa a sessão fornecida.

Quando um serviço WCF aceita uma sessão de cliente, os seguintes recursos são habilitados por padrão:

  1. Todas as chamadas entre um objeto cliente WCF são tratadas pela mesma instância de serviço.

  2. Associações baseadas em sessão diferentes fornecem recursos adicionais.

Tipos de sessão System-Provided

Uma associação baseada em sessão dá suporte à associação padrão de uma instância de serviço com uma sessão específica. No entanto, diferentes associações baseadas em sessão dão suporte a recursos diferentes, além de habilitar o controle de instanciação baseado em sessão descrito anteriormente.

O WCF fornece os seguintes tipos de comportamento de aplicativo baseado em sessão:

Definir a propriedade SessionMode não especifica o tipo de sessão que o contrato exige, apenas que ela exija uma.

Criando um contrato que requer uma sessão

A criação de um contrato que exige uma sessão indica que o grupo de operações que o contrato de serviço declara deve ser executado na mesma sessão e que as mensagens devem ser entregues em ordem. Para afirmar o nível de suporte de sessão exigido por um contrato de serviço, defina a propriedade ServiceContractAttribute.SessionMode em sua interface ou classe de contrato de serviço como o valor da enumeração System.ServiceModel.SessionMode para especificar se o contrato:

  • Requer uma sessão.

  • Permite que um cliente estabeleça uma sessão.

  • Proíbe uma sessão.

A configuração da propriedade SessionMode, no entanto, não especifica o tipo de comportamento baseado em sessão que o contrato requer. Ele instrui o WCF a confirmar em tempo de execução que a associação configurada (que cria o canal de comunicação) para o serviço faz, não faz ou pode estabelecer uma sessão ao implementar um serviço. Novamente, a associação pode atender a esse requisito com qualquer tipo de comportamento baseado em sessão escolhido: segurança, transporte, confiável ou alguma combinação. O comportamento exato depende do valor System.ServiceModel.SessionMode selecionado. Se a associação configurada do serviço não estiver em conformidade com o valor de SessionMode, uma exceção será gerada. As associações e os canais que eles criam que dão suporte às sessões são considerados baseados em sessão.

O contrato de serviço a seguir especifica que todas as operações no ICalculatorSession devem ser trocadas em uma sessão. Nenhuma das operações retorna um valor para o chamador, exceto o método Equals. No entanto, o método Equals não usa parâmetros e, portanto, só pode retornar um valor não zero dentro de uma sessão na qual os dados já foram passados para as outras operações. Esse contrato requer que uma sessão funcione corretamente. Sem uma sessão associada a um cliente específico, a instância de serviço não tem como saber quais dados anteriores esse cliente enviou.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
    [OperationContract(IsOneWay=true)]
    void Clear();
    [OperationContract(IsOneWay = true)]
    void AddTo(double n);
    [OperationContract(IsOneWay = true)]
    void SubtractFrom(double n);
    [OperationContract(IsOneWay = true)]
    void MultiplyBy(double n);
    [OperationContract(IsOneWay = true)]
    void DivideBy(double n);
    [OperationContract]
    double Equals();
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession

    <OperationContract(IsOneWay:=True)> _
    Sub Clear()
    <OperationContract(IsOneWay:=True)> _
    Sub AddTo(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub SubtractFrom(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub MultiplyBy(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub DivideBy(ByVal n As Double)
    <OperationContract()> _
    Function Equal() As Double
End Interface

Se um serviço permitir uma sessão, uma sessão será estabelecida e usada se o cliente iniciar uma; caso contrário, nenhuma sessão é estabelecida.

Sessões e Instâncias de Serviço

Se você usar o comportamento de instancamento padrão no WCF, todas as chamadas entre um objeto cliente WCF serão tratadas pela mesma instância de serviço. Portanto, no nível do aplicativo, você pode considerar uma sessão como habilitando o comportamento do aplicativo semelhante ao comportamento de chamada local. Por exemplo, quando você cria um objeto local:

  • Um construtor é chamado.

  • Todas as chamadas subsequentes feitas para a referência de objeto do cliente WCF são processadas pela mesma instância de objeto.

  • Um destruidor é chamado quando a referência de objeto é destruída.

As sessões permitem um comportamento semelhante entre clientes e serviços, desde que o comportamento da instância de serviço padrão seja usado. Se um contrato de serviço exigir ou dar suporte a sessões, uma ou mais operações de contrato poderão ser marcadas como iniciando ou encerrando uma sessão definindo as propriedades IsInitiating e IsTerminating.

As operações de início são aquelas que devem ser chamadas como a primeira operação de uma nova sessão. Iniciar operações não pode ser chamado somente após pelo menos uma operação iniciando foi chamada. Portanto, você pode criar um tipo de construtor de sessão para seu serviço declarando operações de início projetadas para obter a entrada de clientes apropriados para o início da instância de serviço. (O estado está associado à sessão, no entanto, e não ao objeto de serviço.)

Operações de encerramento, por outro lado, são aquelas que devem ser chamadas como a última mensagem em uma sessão existente. Em casos padrão, WCF recicla o objeto de serviço e seu contexto após a sessão com que o serviço foi associado é fechada. Portanto, você pode criar um tipo de destruidor declarando operações de encerramento projetadas para executar uma função apropriada ao final da instância de serviço.

Observação

Embora o comportamento padrão tenha uma semelhança com construtores e destruidores locais, é apenas uma semelhança. Qualquer operação de serviço do WCF pode ser uma operação de iniciação ou encerramento, ou ambas ao mesmo tempo. Além disso, no caso padrão, as operações de início podem ser chamadas várias vezes em qualquer ordem; nenhuma sessão adicional é criada depois que a sessão é estabelecida e associada a uma instância, a menos que você controle explicitamente o tempo de vida da instância de serviço (manipulando o objeto System.ServiceModel.InstanceContext). Por fim, o estado está associado à sessão e não ao objeto de serviço.

Por exemplo, o contrato ICalculatorSession usado no exemplo anterior requer que o objeto cliente WCF primeiro chame a operação Clear antes de qualquer outra operação e que a sessão com esse objeto cliente WCF deve ser encerrada quando ele chama a operação Equals. O exemplo de código a seguir mostra um contrato que impõe esses requisitos. Clear deve ser chamado primeiro para iniciar uma sessão e essa sessão termina quando Equals é chamada.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
    [OperationContract(IsOneWay=true, IsInitiating=true, IsTerminating=false)]
    void Clear();
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void AddTo(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void SubtractFrom(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void MultiplyBy(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void DivideBy(double n);
    [OperationContract(IsInitiating = false, IsTerminating = true)]
    double Equals();
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession

    <OperationContract(IsOneWay:=True, IsInitiating:=True, IsTerminating:=False)> _
    Sub Clear()
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub AddTo(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub SubtractFrom(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub MultiplyBy(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub DivideBy(ByVal n As Double)
    <OperationContract(IsInitiating:=False, IsTerminating:=True)> _
    Function Equal() As Double
End Interface

Os serviços não iniciam sessões com clientes. Em aplicativos cliente WCF, existe uma relação direta entre o tempo de vida do canal baseado em sessão e o tempo de vida da sessão em si. Dessa forma, os clientes criam novas sessões criando novos canais baseados em sessão e derrubam sessões existentes fechando canais baseados em sessão normalmente. Um cliente inicia uma sessão com um ponto de extremidade de serviço chamando um dos seguintes:

Normalmente, um cliente encerra uma sessão com um ponto de extremidade de serviço chamando um dos seguintes:

  • ICommunicationObject.Close no canal retornado por uma chamada para ChannelFactory<TChannel>.CreateChannel.

  • ClientBase<TChannel>.Close no objeto cliente WCF gerado por Svcutil.exe.

  • Uma operação de encerramento em qualquer tipo de objeto cliente WCF (por padrão, nenhuma operação está sendo encerrada; o contrato deve especificar explicitamente uma operação de encerramento). Quando a primeira operação é chamada, o objeto cliente WCF abre automaticamente o canal e inicia uma sessão.

Para obter exemplos, consulte Como criar um serviço que requer sessões, bem como Comportamento de serviço padrão e Instanciação.

Para obter mais informações sobre clientes e sessões, consulte Acessando serviços usando um cliente WCF.

Sessões interagem com configurações de InstanceContext

Há uma interação entre a enumeração SessionMode em um contrato e a propriedade ServiceBehaviorAttribute.InstanceContextMode, que controla a associação entre canais e objetos de serviço específicos. Para obter mais informações, consulte Sessões, Instanciação e Simultaneidade.

Compartilhando objetos InstanceContext

Você também pode controlar qual canal ou chamada baseado em sessão está associado a qual objeto InstanceContext executando essa associação por conta própria.

Sessões e streaming

Quando você tiver uma grande quantidade de dados para transferência, o modo de transferência de streaming do WCF será uma alternativa viável para o comportamento padrão de buffer e processamento de mensagens na memória em sua totalidade. Você pode obter um comportamento inesperado durante o streaming de chamadas com uma associação baseada em sessão. Todas as chamadas de streaming são feitas por um único canal (o canal de datagrama) que não oferece suporte a sessões mesmo que a associação que está sendo usada esteja configurada para usar sessões. Se vários clientes fizerem chamadas de streaming para o mesmo objeto sobre uma associação baseada em sessão, e o modo de simultaneidade do serviço estiver definido como único, e o modo de contexto de sua instância estiver definido como PerSession, todas as chamadas deverão passar pelo canal de datagrama e, portanto, apenas uma chamada será processada de cada vez. Portanto, um ou mais clientes podem atingir o tempo limite. Você pode contornar esse problema definindo o InstanceContextMode do objeto de serviço como PerCall ou a Simultaneidade como Múltipla.

Observação

MaxConcurrentSessions não tem efeito nesse caso porque há apenas uma "sessão" disponível.

Confira também