Использование сеансов

В приложениях Windows Communication Foundation (WCF) сеанс сопоставляет группу сообщений с беседой. Сеансы WCF отличаются от объекта сеанса, доступного в ASP.NET приложениях, поддерживают различные поведение и управляются разными способами. В этом разделе описываются функции, которые поддерживаются сеансами в приложениях WCF и как их использовать.

Сеансы в приложениях Windows Communication Foundation

Если в контракте службы указано, что для него требуется сеанс, это означает, что все вызовы (т. е. обмен сообщениями, на котором он основан) должны быть частью одного диалога. Если в контракте указано, что сеансы для него разрешены, но не требуются, клиенты могут подключаться, создавая сеанс или не создавая его. Если сеанс завершен и по его каналу отправляется сообщение, выдается исключение.

Сеансы WCF имеют следующие основные концептуальные функции:

  • Они явным образом инициируются и завершаются вызвавшим приложением (клиентом WCF).

  • Сообщения, доставленные в ходе сеанса, обрабатываются в порядке их получения.

  • Сеанс коррелирует группу сообщений в диалог. Возможны различные типы корреляций. Например, один основанный на сеансах канал может коррелировать сообщения, основываясь на общем сетевом подключении, а другой - основываясь на общем теге в тексте сообщения. Функции, получаемые в результате сеанса, зависят от характера корреляции.

  • Общее хранилище данных не связано с сеансом WCF.

Если вы знакомы с классом System.Web.SessionState.HttpSessionState в ASP.NET приложениях и функциональных возможностях, которые он предоставляет, вы можете заметить следующие различия между этим типом сеансов и сеансов WCF:

  • ASP.NET сеансы всегда инициируются сервером.

  • ASP.NET сеансы неявно неупорядочены.

  • ASP.NET сеансы предоставляют общий механизм хранения данных в запросах.

Содержание этого раздела:

  • Поведение выполнения по умолчанию при использовании привязок, основанных на сеансе, в уровне модели службы.

  • Типы функций, предоставляемых сеансами WCF, предоставляемые системой привязки.

  • Создание контракта, объявляющего требование сеанса.

  • Управление созданием и прекращением сеанса и его связью с экземпляром службы.

Поведение выполнения по умолчанию с использованием сеансов

Привязка, пытающаяся инициировать сеанс, называется основанной на сеансе . Контракты служб указывают о том, что для них требуются, допускаются или не допускаются привязки, основанные на сеансе. Для этого свойству ServiceContractAttribute.SessionMode интерфейса (или класса) контракта службы присваивается одно из значений перечисления System.ServiceModel.SessionMode . По умолчанию значение этого свойства — Allowedэто означает, что если клиент использует привязку на основе сеанса с реализацией службы WCF, служба устанавливает и использует предоставленный сеанс.

Если служба WCF принимает сеанс клиента, по умолчанию включены следующие функции:

  1. Все вызовы между клиентским объектом WCF обрабатываются тем же экземпляром службы.

  2. Различные привязки на основе сеанса предоставляют дополнительные возможности.

Типы сеансов, предоставляемые системой

Привязка, основанная на сеансе, поддерживает ассоциацию по умолчанию экземпляра службы с определенным сеансом. Впрочем, различные привязки, основанные на сеансе, поддерживают и другие различные функции, помимо описанного выше управления созданием экземпляров на основе сеанса.

WCF предоставляет следующие типы поведения приложений на основе сеансов:

  • Элемент System.ServiceModel.Channels.SecurityBindingElement поддерживает основанные на безопасности сеансы, в которых обе стороны, обменивающиеся информацией, согласовали определенный безопасный диалог. Дополнительные сведения см. в разделе "Защита служб". Например, привязка System.ServiceModel.WSHttpBinding , содержащая поддержку как безопасных, так и надежных сеансов, по умолчанию использует только безопасный сеанс, шифрующий сообщения и защищающий их цифровой подписью.

  • Привязка System.ServiceModel.NetTcpBinding поддерживает сеансы, основанные на TCP/IP, что обеспечивает корреляцию всех сообщений по подключению на уровне сокетов.

  • Элемент System.ServiceModel.Channels.ReliableSessionBindingElement , реализующий спецификацию WS-ReliableMessaging, обеспечивает поддержку надежных сеансов, в которых можно настроить отправку сообщений в определенном порядке и только один раз, что гарантирует получение сообщений, даже когда при диалоге они проходят через несколько узлов. Дополнительные сведения см. в разделе "Надежные сеансы".

  • Привязка System.ServiceModel.NetMsmqBinding обеспечивает сеансы датаграммы MSMQ. Дополнительные сведения см. в разделе "Очереди" в WCF.

Установка свойства SessionMode указывает о том, что для контракта требуется сеанс, но не задает тип этого сеанса.

Создание контракта, требующего сеанс

Создание контракта, требующего сеанс, означает, что группа операций, объявляемых контрактом службы, должна выполняться в пределах одного сеанса и сообщения должны быть доставлены в определенном порядке. Чтобы назначить уровень поддержки сеансов, требуемый контрактом, задайте в качестве значения свойства ServiceContractAttribute.SessionMode класса или интерфейса контракта службы перечисление System.ServiceModel.SessionMode . При этом указывается одно из следующих условий контракта:

  • Требуется сеанс.

  • Клиенту допускается создавать сеанс.

  • Сеансы запрещены.

Впрочем, установка свойства SessionMode не указывает требуемый контрактом тип поведения, основанного на сеансе. Он указывает WCF подтвердить во время выполнения, что настроенная привязка (которая создает канал связи) для службы, не делает или может установить сеанс при реализации службы. Опять же, привязка может выполнить это требование с любым типом поведения, основанного на сеансе: безопасность, транспорт, надежность или некоторая комбинация этих типов. Конкретное поведение зависит от выбранного значения System.ServiceModel.SessionMode . Если настроенная для службы привязка не соответствует значению SessionMode, выдается исключение. Привязки и создаваемые ими каналы, поддерживающие сеансы, называются основанными на сеансах.

Следующий контракт службы указывает, что все операции в ICalculatorSession необходимо выполнить в пределах одного сеанса. Ни одна операция не возвращает значение вызвавшему объекту, за исключением метода Equals . Впрочем, метод Equals не принимает параметры, а потому может возвращать только ненулевое значение в пределах сеанса, в котором данные уже переданы другим операциям. Для правильной работы этого контракта требуется сеанс. При отсутствии сеанса, связанного с определенным клиентом, экземпляр службы не может определить, какие именно данные отправил клиент.

[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

Если сеанс разрешен службой, он создается и используется, если он инициирован клиентом. В противном случае сеанс не создается.

Сеансы и экземпляры служб

Если в WCF используется поведение по умолчанию, все вызовы между клиентским объектом WCF обрабатываются тем же экземпляром службы. Таким образом, на уровне приложения можно считать, что сеанс обеспечивает поведение приложений, аналогичное поведению местных вызовов. Например, при создании локального объекта происходит следующее:

  • Вызывается конструктор.

  • Все последующие вызовы, выполненные в ссылке на клиентский объект WCF, обрабатываются тем же экземпляром объекта.

  • Деструктор вызывается при уничтожении ссылки на объект.

Сеансы обеспечивают аналогичное поведение при взаимодействии между клиентами и службами, если используется поведение создания экземпляров службы по умолчанию. Если контракт службы требует или поддерживает сеансы, можно отметить операцию (или несколько операций) как инициирующую или завершающую сеанс. Для этого необходимо задать свойства IsInitiating и IsTerminating .

Инициирующие операции - это операции, вызываемые в качестве первых операций новых сеансов. Неинициирующие операции могут вызываться только после вызова по крайней мере одной инициирующей операции. Поэтому можно создать некоторое подобие конструктора сеансов для службы, объявив инициирующие операции, которые принимают от клиентов входные данные, как подходящие для создания экземпляра службы. (Впрочем, состояние ассоциируется с сеансом, а не с объектом службы.)

Завершающие операции- это, соответственно, операции, вызываемые как последние сообщения существующих сеансов. В случае по умолчанию WCF повторно использует объект службы и его контекст после закрытия сеанса, с которым была связана эта служба. Поэтому можно создать некоторое подобие деструктора, объявив завершающие операции, которые выполняют функции по завершению действия экземпляра службы.

Примечание.

Поведение по умолчанию имеет сходство с локальными конструкторами и деструкторами, но это не более чем сходство. Любая операция службы WCF может быть операцией, инициирующей или завершающейся, или одновременной. Кроме того, в случае по умолчанию инициирующие операции можно вызывать сколько угодно раз и в любом порядке. После того как сеанс установлен и связан с экземпляром, дополнительные сеансы могут быть созданы только в случае осуществления явным образом управления временем существования экземпляра службы (путем обработки объекта System.ServiceModel.InstanceContext ). И наконец, состояние связывается с сеансом, а не с объектом службы.

Например, контракт, используемый в предыдущем примере, ICalculatorSession требует, чтобы клиентский объект WCF сначала вызвал Clear операцию перед любой другой операцией и что сеанс с этим клиентским объектом WCF должен завершиться при вызове Equals операции. В следующем примере кода приведен контракт, обеспечивающий выполнение этих требований. Для инициации сеанса сначала необходимо вызвать операциюClear , а завершится сеанс при вызове операции Equals .

[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

Службы не начинают сеансы с клиентами. В клиентских приложениях WCF прямая связь существует между временем существования канала на основе сеанса и временем существования самого сеанса. Таким образом, клиенты создают новые сеансы путем создания новых каналов, основанных на сеансах, и прерывают существующие сеансы путем правильного закрытия этих каналов. Клиент начинает сеанс с конечной точкой службы путем вызова одной из следующих операций:

Обычно клиент завершает сеанс с конечной точкой службы путем вызова одной из следующих операций:

  • ICommunicationObject.Close для канала, возвращенного при вызове ChannelFactory<TChannel>.CreateChannel.

  • ClientBase<TChannel>.Close на объекте клиента WCF, созданном Svcutil.exe.

  • Завершающая операция для любого типа клиентского объекта WCF (по умолчанию никакие операции не завершаются; контракт должен явно указать завершающее операцию). При вызове первой операции объект клиента WCF автоматически открывает канал и инициирует сеанс.

Примеры см. в разделе How to: Create a Service That Requires Sessions , а также в примерах из разделов Default Service Behavior и Instancing .

Дополнительные сведения о клиентах и сеансах см. в разделе Accessing Services Using a WCF Client.

Сеансы взаимодействуют с параметрами InstanceContext

Перечисление SessionMode контракта взаимодействует со свойством ServiceBehaviorAttribute.InstanceContextMode , управляющим связью между каналами и определенными объектами службы. Дополнительные сведения см. в разделе "Сеансы", "Instancing" и "Параллелизм".

Совместное использование объектов InstanceContext

Также можно задать для каждого вызова или канала, основанного на сеансе, с каким именно объектом InstanceContext он будет ассоциирован, самостоятельно назначив ассоциацию.

Сеансы и потоковая передача

При наличии большого объема данных для передачи режим потоковой передачи в WCF является возможным вариантом поведения по умолчанию буферизации и обработки сообщений в памяти в целом. При потоковой передаче вызовов с привязкой, основанной на сеансе, может возникнуть непредвиденное поведение. Все потоковые вызовы выполняются через один канал (канал датаграммы), который не поддерживает сеансы, даже если используемая привязка настроена так, чтобы она использовала сеансы. Если несколько клиентов выполняют потоковые вызовы одного объекта службы через привязку, основанную на сеансе, и задан "одиночный" режим параллелизма объекта службы и задан режим контекста его экземпляра PerSession, все вызовы должны проходить через канал датаграммы, а потому может обрабатываться не более одного вызова одновременно. Один или несколько клиентов могут отсюстить. Эту проблему можно обойти, установив для объекта InstanceContextMode службы значение PerCall или параллелизм нескольких.

Примечание.

Свойство MaxConcurrentSessions в данном случае ни на что не влияет, поскольку имеется всего один сеанс.

См. также