Partilhar via


Usando sessões

Em aplicativos WCF (Windows Communication Foundation), uma sessão correlaciona um grupo de mensagens em uma conversa. As sessões WCF são diferentes do objeto de sessão disponível em aplicativos ASP.NET, oferecem 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 em aplicativos do Windows Communication Foundation

Quando um contrato de serviço especifica que requer uma sessão, esse contrato está especificando que todas as chamadas (ou seja, as trocas de mensagens subjacentes que suportam as chamadas) devem fazer parte da mesma conversa. Se um contrato especificar que 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 através do mesmo canal, uma exceção será lançada.

As sessões WCF têm as seguintes características conceituais principais:

  • Eles são explicitamente iniciados e encerrados 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. São possíveis diferentes tipos de correlação. 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 tag compartilhada no corpo da mensagem. Os recursos que podem ser derivados da sessão dependem da natureza da correlação.

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

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

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

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

  • ASP.NET sessões 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 baseadas em sessão e fornecidas pelo sistema do WCF fornecem.

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

  • Como entender e controlar a criação e o término 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 ServiceContractAttribute.SessionMode propriedade na interface (ou classe) do contrato de serviço para um dos System.ServiceModel.SessionMode valores de enumeração. 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 de cliente WCF são tratadas pela mesma instância de serviço.

  2. Diferentes associações baseadas em sessão fornecem recursos adicionais.

Tipos de sessão fornecidos pelo sistema

Uma associação baseada em sessão suporta a 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 suportam recursos diferentes, além de habilitar o controle de instanciação baseado em sessão descrito anteriormente.

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

A definição da SessionMode propriedade não especifica o tipo de sessão que o contrato exige, apenas que requer uma.

Criando um contrato que requer uma sessão

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

  • Requer uma sessão.

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

  • Proíbe uma sessão.

No entanto, a definição da SessionMode propriedade não especifica o tipo de comportamento baseado em sessão que o contrato exige. 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 estabelece ou pode estabelecer uma sessão ao implementar um serviço. Novamente, a associação pode satisfazer esse requisito com qualquer tipo de comportamento baseado em sessão que escolher — segurança, transporte, confiabilidade ou alguma combinação. O comportamento exato depende do System.ServiceModel.SessionMode valor selecionado. Se a associação configurada do serviço não estiver em conformidade com o valor de SessionMode, uma exceção será lançada. Diz-se que as ligações e os canais que criam para as sessões de suporte são baseados em sessão.

O contrato de serviço a seguir especifica que todas as operações no devem ser trocadas ICalculatorSession dentro de uma sessão. Nenhuma das operações retorna um valor para o chamador, exceto o Equals método. No entanto, o Equals método não usa parâmetros e, portanto, só pode retornar um valor diferente de zero dentro de uma sessão na qual os dados já foram passados para as outras operações. Este contrato requer uma sessão para funcionar 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 permite uma sessão, então uma sessão é estabelecida e usada se o cliente iniciar uma; caso contrário, nenhuma sessão será estabelecida.

Sessões e instâncias de serviço

Se você usar o comportamento de instanciação padrão no WCF, todas as chamadas entre um objeto de cliente WCF serão tratadas pela mesma instância de serviço. Portanto, no nível do aplicativo, você pode pensar em 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 do 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 suportar sessões, uma ou mais operações de contrato podem ser marcadas como iniciando ou encerrando uma sessão definindo as IsInitiating propriedades e IsTerminating .

Iniciando operações são aquelas que devem ser chamadas como a primeira operação de uma nova sessão. As operações não iniciadoras só podem ser chamadas depois de pelo menos uma operação inicial ter sido chamada. Portanto, você pode criar um tipo de construtor de sessão para seu serviço declarando operações iniciais projetadas para receber informações de clientes apropriadas para o início da instância de serviço. (No entanto, o estado está associado à sessão, e não ao objeto de serviço.)

As operações de encerramento, por outro lado, são aquelas que devem ser chamadas como a última mensagem em uma sessão existente. No caso padrão, o WCF recicla o objeto de serviço e seu contexto depois que a sessão à qual 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.

Nota

Embora o comportamento padrão tenha uma semelhança com construtores e destruidores locais, é apenas uma semelhança. Qualquer operação de serviço WCF pode ser uma operação inicial ou encerrada, ou ambas ao mesmo tempo. Além disso, no caso padrão, as operações iniciais podem ser chamadas a qualquer número de 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 System.ServiceModel.InstanceContext objeto). Finalmente, o estado está associado à sessão e não ao objeto de serviço.

Por exemplo, o ICalculatorSession contrato usado no exemplo anterior requer que o objeto de cliente WCF primeiro chame a Clear operação antes de qualquer outra operação e que a sessão com esse objeto de cliente WCF seja encerrada quando ele chamar a Equals operação. 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. Como tal, os clientes criam novas sessões criando novos canais baseados em sessão e destroem 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 termina 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 de cliente WCF gerado por Svcutil.exe.

  • Uma operação de encerramento em qualquer tipo de objeto de cliente WCF (por padrão, nenhuma operação é encerrada; o contrato deve especificar explicitamente uma operação de encerramento). Quando a primeira operação é chamada, o objeto de 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 o comportamento de serviço padrão e exemplos de instanciação.

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

As sessões interagem com as configurações do InstanceContext

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

Compartilhando objetos InstanceContext

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

Sessões e Streaming

Quando você tem uma grande quantidade de dados para transferir, o modo de transferência de streaming no WCF é uma alternativa viável para o comportamento padrão de buffer e processamento de mensagens na memória em sua totalidade. Você pode ter um comportamento inesperado ao transmitir chamadas com uma associação baseada em sessão. Todas as chamadas de streaming são feitas através de um único canal (o canal de datagrama) que não suporta 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 de serviço por meio de uma associação baseada em sessão, e o modo de simultaneidade do objeto de serviço estiver definido como único e seu modo de contexto de 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. Um ou mais clientes podem então atingir o tempo limite. Você pode contornar esse problema definindo o objeto de InstanceContextMode serviço como PerCall ou Simultaneidade como múltiplo.

Nota

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

Consulte também